POJ3693 Maximum repetition substring

Maximum repetition substring
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 11130   Accepted: 3431

Description

The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1.

Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.

Input

The input consists of multiple test cases. Each test case contains exactly one line, which
gives a non-empty string consisting of lowercase letters. The length of the string will not be greater than 100,000.

The last test case is followed by a line containing a '#'.

Output

For each test case, print a line containing the test case number( beginning with 1) followed by the substring of maximum repetition number. If there are multiple substrings of maximum repetition number, print the lexicographically smallest one.

Sample Input

ccabababc
daabbccaa
#

Sample Output

Case 1: ababab
Case 2: aa

Source

 

【题解】

枚举循环节长度L,不难发现对于1,l+L,1+2L,1+3l,.......,l+kL<=n这些位置上的字符,一定存在相邻字符在两个相邻长度为L的循环节里。注意,这里仅仅说存在,没有说存在几个,可能这两个字符代表的长度上有多个重叠的不同循环节。但我们只需求出最大可行的循环节个数及其对应的循环节长度即可。

对于相邻的1 + kL, 1 + kL + L,求LCP,若L | LCP,则L满足要求,循环节个数为LCP / L + 1,长度为L;否则左移L - k%L,再求LCP,重复上述过程。

只需证明存在循环节长度为L的子串一定能被找到,比较显然,留给大家了

找的时候记录下所有可行的最大循环节个数的循环节长度,还需证明最大循环节个数所有的循环节长度都能被找到,相当于枚举循环节长度命中的位置,找到的是尽可能大的循环节个数,这也是显然的。

于是这个算法正确性就是显然的(显然了老半天我才显然出十分显然的证明来。。。。)

求出最大可行的循环节个数及其对应的循环节长度,枚举所有sa[i]和可行长度,判断即可

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <vector>
  8 #include <cmath> 
  9 #define min(a, b) ((a) < (b) ? (a) : (b))
 10 #define max(a, b) ((a) > (b) ? (a) : (b))
 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
 12 template <class T>
 13 inline void swap(T& a, T& b)
 14 {
 15     T tmp = a;a = b;b = tmp;
 16 }
 17 inline void read(int &x)
 18 {
 19     x = 0;char ch = getchar(), c = ch;
 20     while(ch < '0' || ch > '9') c = ch, ch = getchar();
 21     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
 22     if(c == '-') x = -x;
 23 }
 24 
 25 const int INF = 0x3f3f3f3f;
 26 const int MAXN = 1000000 + 10;
 27 
 28 int pow2[30], lo2[MAXN];
 29 
 30 struct SuffixArray
 31 {
 32     char s[MAXN];int sa[MAXN], rank[MAXN], height[MAXN], t1[MAXN], t2[MAXN], n, c[MAXN];
 33     
 34     int stmi[MAXN][30];
 35     
 36     void clear(){n = 0;memset(sa, 0, sizeof(sa));}
 37     void build_sa(int m)
 38     {
 39         int i, *x = t1, *y = t2;
 40         for(i = 0;i <= m;++ i) c[i] = 0;
 41         for(i = 1;i <= n;++ i) ++ c[x[i] = s[i]];
 42         for(i = 1;i <= m;++ i) c[i] += c[i - 1];
 43         for(i = n;i;-- i) sa[c[x[i]] --] = i;
 44         for(int k = 1;k <= n;k <<= 1)
 45         {
 46             int p = 0;
 47             for(i = n - k + 1;i <= n;++ i) y[++ p] = i;
 48             for(i = 1;i <= n;++ i) if(sa[i] > k) y[++ p] = sa[i] - k;
 49             for(i = 0;i <= m;++ i) c[i] = 0;
 50             for(i = 1;i <= n;++ i) ++ c[x[y[i]]];
 51             for(i = 1;i <= m;++ i) c[i] += c[i - 1];
 52             for(i = n;i;-- i) sa[c[x[y[i]]] --] = y[i];
 53             swap(x, y);p = 0,x[sa[1]] = ++ p;
 54             for(i = 2;i <= n;++ i) x[sa[i]] = sa[i] + k <= n && sa[i - 1] + k <= n && y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p : ++ p;
 55             if(p >= n) break;m = p;
 56         }
 57     }
 58     void build_height()
 59     {
 60         int i,j,k = 0;
 61         for(i = 1;i <= n;++ i) rank[sa[i]] = i;
 62         for(i = 1;i <= n;++ i)
 63         {
 64             if(k) -- k; if(rank[i] == 1) continue;
 65             j = sa[rank[i] - 1];
 66             while(i + k <= n && j + k <= n && s[i + k] == s[j + k]) ++ k;
 67             height[rank[i]] = k;
 68         }
 69     }
 70     void build_st()
 71     {
 72         for(int i = 1;i <= n;++ i) stmi[i][0] = height[i];
 73         for(int j = 1;pow2[j] <= n;++ j)
 74             for(int i = 1;i <= n;++ i)
 75                 if(i + pow2[j - 1] <= n) stmi[i][j] = min(stmi[i][j - 1], stmi[i + pow2[j - 1]][j - 1]);
 76                 else stmi[i][j] = stmi[i][j - 1];
 77     }
 78     int getmin(int x, int y)
 79     {
 80         return min(stmi[x][lo2[y - x + 1]], stmi[y - pow2[lo2[y - x + 1]] + 1][lo2[y - x + 1]]);
 81     }
 82     int LCP(int x, int y)
 83     {
 84         if(rank[x] + 1 > rank[y]) swap(x, y);
 85         return getmin(rank[x] + 1, rank[y]);
 86     }
 87 }A;
 88 
 89 int ca, ma, ans[MAXN], tot;
 90 
 91 int main()
 92 {
 93     pow2[0] = 1;
 94     for(int i = 1;i < 30;++ i) pow2[i] = pow2[i - 1] << 1;
 95     lo2[1] = 0;
 96     for(int i = 2;i <= 200000;++ i) lo2[i] = lo2[i >> 1] + 1;
 97     while(scanf("%s", A.s + 1) != EOF && A.s[1] != '#')
 98     {
 99         ++ ca, A.n = strlen(A.s + 1);ma = tot = 0;
100         A.build_sa('z' + 1);A.build_height();A.build_st();
101         for(register int L = 1;L <= A.n >> 1;++ L)
102         {
103             for(int l = 1,r = L + 1;r <= A.n;l += L, r += L)
104             {
105                 int k = A.LCP(l, r), t = (L - k % L); 
106                 if(k % L == 0)
107                 {
108                     if(k / L + 1 > ma) ma = k / L + 1, ans[tot = 1] = L;
109                     else if(k / L + 1 == ma) ans[++ tot] = L;
110                 }
111                 else if(l - t >= 1 && r - t >= 1)
112                 {
113                     k = A.LCP(l - t, r - t);
114                     if(k && k % L == 0)
115                     {
116                         if(k / L + 1 > ma) ma = k / L + 1, ans[tot = 1] = L;
117                         else if(k / L + 1 == ma) ans[++ tot] = L;
118                     }
119                 }
120             }
121         }
122         printf("Case %d: ", ca);
123         int flag = 0, s = 0, t = 0;
124         for(int i = 1;i <= A.n;++ i)
125             if(flag) break;
126             else 
127                 for(int j = 1;j <= tot;++ j)
128                     if(A.sa[i] + ma * ans[j] - 1<= A.n && A.LCP(A.sa[i], A.sa[i] + ans[j]) >= (ma - 1) * ans[j])
129                     {
130                         flag = 1;s = A.sa[i];t = A.sa[i] + ma * ans[j] - 1;break;
131                     }
132         for(int i = s;i <= t;++ i) printf("%c", A.s[i]);
133         putchar('\n');
134         A.clear();
135     }
136     return 0;
137 }
POJ3693

 

 

 

 

 

posted @ 2018-01-23 19:32  嘒彼小星  阅读(205)  评论(0编辑  收藏  举报