后缀数组题目整理
最近在跟着 罗穗骞 的论文学习后缀数组, 不亏是神牛的论文。无论是算法讲解,还是习题举例都非常不错。下面把最进做的几道后缀数组整理一下。
1.两字符串的最长公共子串
1 #include <stdio.h> 2 #include <iostream> 3 #include <algorithm> 4 #include <sstream> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <limits.h> 8 #include <vector> 9 #include <string> 10 #include <time.h> 11 #include <math.h> 12 #include <queue> 13 #include <stack> 14 #include <set> 15 #include <map> 16 #define INF 0x3f3f3f3f 17 #define Zero(x) memset((x),0, sizeof(x)) 18 #define Neg(x) memset((x), -1, sizeof(x)) 19 #define dg(x) cout << #x << " = " << x << endl 20 #define pk(x) push_back(x) 21 #define pok() pop_back() 22 #define eps 1e-8 23 #define pii pair<int, int> 24 #define pi acos(-1.0) 25 using namespace std; 26 typedef long long ll; 27 bool debug = true; 28 int OK = 1; 29 const int maxn = 220000; 30 int sa[maxn], r[maxn], height[maxn], t1[maxn], t2[maxn], c[maxn]; 31 int rk[maxn]; 32 char str[maxn]; 33 bool cmp(int *r, int a,int b, int l){ 34 return r[a] == r[b] && r[a + l] == r[b + l]; 35 } 36 37 void da(int str[], int sa[], int rk[], int height[], int n, int m){ 38 n++; 39 int i, j, p, *x = t1, *y = t2; 40 for(i = 0; i < m; i++) c[i] = 0; 41 for(i = 0; i < n; ++i) c[x[i] = str[i]]++; 42 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 43 for(i = n - 1; i >= 0; --i) sa[--c[x[i]]] = i; 44 for(j = 1; j <= n; j <<= 1){ 45 p = 0; 46 for(i = n - j; i < n; ++i) y[p++] = i; 47 for(i = 0; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; 48 for(i = 0; i < m; ++i) c[i] = 0; 49 for(i = 0; i < n; ++i) c[x[y[i]]]++; 50 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 51 for(i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i]; 52 swap(x, y); 53 p = 1; x[sa[0]] = 0; 54 for(i = 1; i < n; ++i) 55 x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1: p++; 56 if(p >= n) break; 57 m = p; 58 } 59 int k = 0; 60 n--; 61 for(i = 0; i <= n; ++i) rk[sa[i]] = i; 62 for(i = 0; i <n ; ++i){ 63 if(k) k--; 64 j = sa[rk[i] - 1]; 65 while(str[i + k] == str[j + k]) ++k; 66 height[rk[i]] = k; 67 } 68 } 69 int main(){ 70 //freopen("data.in","r",stdin); 71 //freopen("data.out","w",stdout); 72 //cin.sync_with_stdio(false); 73 while(scanf("%s", str) != EOF){ 74 int len = strlen(str); 75 int len1 = len; 76 str[len] = '9'; 77 scanf("%s", str + len + 1); 78 len = strlen(str); 79 for(int i = 0; i < len; ++i) r[i] = str[i]; 80 r[len] = 0; 81 da(r, sa, rk, height, len, 128); 82 int mx = 0; 83 for(int i = 2; i < len; ++i){ 84 if(mx < height[i] && (sa[i] > len1 && sa[i - 1] < len1 || sa[i] < len1 && sa[i - 1] > len1)){ 85 mx = height[i]; 86 } 87 } 88 cout << mx << endl; 89 } 90 return 0; 91 }
2.不可重叠最长重复子串poj 1743( 二分长度k, height数组划分)
/********Good Luck********* * *Author: yeahpeng * *Time: 2015-10-05-22.33 * **************************/ //#pragma comment(linker, "/STACK:102400000,102400000") #define _CRT_SECURE_NO_WARNINGS #include <algorithm> #include <bitset> #include <cassert> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <iostream> #include <list> #include <map> #include <numeric> #include <queue> #include <set> #include <sstream> #include <stack> #include <string> #include <vector> #ifdef DEBUG_yp #define dg(x) cout << #x << " = " << x << endl #define dg2(x1, x2) cout << #x1 << " = " << x1 << ", " << #x2 << " = " << x2 << endl #define dg3(x1, x2, x3) cout << #x1 << " = " << x1 << ", " << #x2 << " = " << x2 << ", " << #x3 << " = " << x3 << endl #define dgarr(arr, n) arrout(arr, n); #else #define dg(x) ; #define dg2(x1, x2) ; #define dg3(x1, x2, x3) ; #define dgarr(arr, n) ; #endif #define Rep(i, v) for(int i = 0; i < int(v); ++i) #define Rep1(i, v) for(int i = 1; i <= int(v); ++i) #define Repe(i, l, r) for(int i = int(l); i < int(r); ++i) #define Zero(x) memset((x),0, sizeof(x)) #define Neg(x) memset((x), -1, sizeof(x)) #define PK(x) push_back(x) #define PPK() pop_back() #define PII pair<int, int> #define MP(x, y) make_pair((x), (y)) #define F first #define S second using namespace std; typedef long long ll; void arrout(int arr[], int len){ for(int i = 0; i <= len; ++i) cout << arr[i] << " "; cout << endl; } int OK = 1; const int INF = 0x3f3f3f3f; const int maxn = 22000; int t1[maxn], t2[maxn], c[maxn]; int rk[maxn], sa[maxn], height[maxn]; bool cmp(int *r, int a, int b, int l){ return r[a] == r[b] && r[a + l] == r[b + l]; } void da(int str[], int sa[], int rk[], int height[], int n, int m){ n++; int i, j, p, *x = t1, *y = t2; for (i = 0; i < m; ++i) c[i] = 0; for (i = 0; i < n; ++i) c[x[i] = str[i]]++; for (i = 1; i < m; ++i) c[i] += c[i - 1]; for (i = n - 1; i >= 0; --i) sa[--c[x[i]]] = i; for (j = 1; j <= n; j <<= 1){ p = 0; for (i = n - j; i < n; ++i) y[p++] = i; for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j; for (i = 0; i < m; ++i) c[i] = 0; for (i = 0; i < n; ++i) c[x[y[i]]]++; for (i = 1; i < m; ++i) c[i] += c[i - 1]; for (i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for (i = 1; i < n; ++i) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++; m = p; } int k = 0; n--; for (i = 0; i <= n; ++i) rk[sa[i]] = i; for(i = 0; i < n; ++i){ if(k)k--; j = sa[rk[i]-1]; while(str[i+k] == str[j+k]) k++; height[rk[i]] = k; } } int n; int arr[maxn], r[maxn]; bool check(int mid){ int mn = INF, mx = 0; for(int i = 2; i <= n; ++i){ if(height[i] >= mid){ mn = INF; mx = 0; while(i<= n && height[i] >= mid){ mn = min(mn, sa[i-1]); mn = min(mn, sa[i]); mx = max(mx, sa[i]); mx = max(mx, sa[i-1]); i++; } if(mx - mn > mid) return true; } } return false; } int main(){ #ifdef DEBUG_yp //freopen("data.out", "w", stdout); //freopen("data.in", "r", stdin); #endif //cin.sync_with_stdio(false);cin.tie(0); while(scanf("%d", &n), n){ for(int i = 0; i < n; ++i) scanf("%d", arr + i); for(int i = 0; i < n-1; ++i) r[i] = arr[i+1] - arr[i] + 100; n--; r[n] = 0; da(r, sa, rk, height, n, 200); int ans = 0; dgarr(height, n); dgarr(sa, n); dgarr(r, n); dgarr(rk, n); int l = 0, rr = n, m; while(l <= rr){ m = (l + rr) >> 1; dg3(m, l, rr); if(check(m)) l = m + 1; else rr = m - 1; } ans = l-1; if(ans >= 4) cout << ans + 1 << endl; else puts("0"); } return 0; }
3.可重叠的最少重复k次的最长重复子串
1 /* 2 ***********Good LUCK********** 3 * Author: yeahpeng 4 * Created Time: 2015/4/24 21:44:34 5 * File Name: poj3693.cpp 6 */ 7 #include <stdio.h> 8 #include <iostream> 9 #include <algorithm> 10 #include <sstream> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <limits.h> 14 #include <vector> 15 #include <string> 16 #include <time.h> 17 #include <math.h> 18 #include <queue> 19 #include <stack> 20 #include <set> 21 #include <map> 22 #define INF 0x3f3f3f3f 23 #define Zero(x) memset((x),0, sizeof(x)) 24 #define Neg(x) memset((x), -1, sizeof(x)) 25 #define dg(x) cout << #x << " = " << x << endl 26 #define pk(x) push_back(x) 27 #define pok() pop_back() 28 #define eps 1e-8 29 #define pii pair<int, int> 30 #define pi acos(-1.0) 31 using namespace std; 32 typedef long long ll; 33 bool debug = false; 34 int OK = 1; 35 const int maxn = 100100; 36 char s[maxn]; 37 int t1[maxn], t2[maxn], c[maxn]; 38 bool cmp(int *r, int a,int b, int l){ 39 return r[a] == r[b] && r[a + l] == r[b + l]; 40 } 41 42 void da(int str[], int sa[], int rk[], int height[], int n, int m){ 43 n++; 44 int i, j, p, *x = t1, *y = t2; 45 for(i = 0; i < m; i++) c[i] = 0; 46 for(i = 0; i < n; ++i) c[x[i] = str[i]]++; 47 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 48 for(i = n - 1; i >= 0; --i) sa[--c[x[i]]] = i; 49 for(j = 1; j <= n; j <<= 1){ 50 p = 0; 51 for(i = n - j; i < n; ++i) y[p++] = i; 52 for(i = 0; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; 53 for(i = 0; i < m; ++i) c[i] = 0; 54 for(i = 0; i < n; ++i) c[x[y[i]]]++; 55 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 56 for(i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i]; 57 swap(x, y); 58 p = 1; x[sa[0]] = 0; 59 for(i = 1; i < n; ++i) 60 x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1: p++; 61 if(p >= n) break; 62 m = p; 63 } 64 int k = 0; 65 n--; 66 for(i = 0; i <= n; ++i) rk[sa[i]] = i; 67 for(i = 0; i <n ; ++i){ 68 if(k) k--; 69 j = sa[rk[i] - 1]; 70 while(str[i + k] == str[j + k]) ++k; 71 height[rk[i]] = k; 72 } 73 } 74 75 int best[20][maxn], mm[maxn]; 76 int rk[maxn], height[maxn], RMQ[maxn],r[maxn]; 77 int sa[maxn]; 78 void initRMQ(int n){ 79 mm[0] = -1; 80 for(int i = 1; i <= n; ++i) 81 mm[i] = ((i&(i - 1)) == 0)?mm[i-1] + 1:mm[i-1]; 82 for(int i = 1; i <= n; ++i) best[0][i] = i; 83 for(int i = 1; i <= mm[n]; ++i) 84 for(int j = 1; j + (1 <<i) - 1 <= n; ++j){ 85 int a = best[i-1][j]; 86 int b = best[i-1][j+(1 << (i-1))]; 87 if(RMQ[a] < RMQ[b]) best[i][j] = a; 88 else best[i][j] = b; 89 } 90 } 91 92 int askRMQ(int a, int b){ 93 int t; 94 t = mm[b - a + 1]; 95 b -= (1 << t) - 1; 96 a = best[t][a]; b = best[t][b]; 97 return RMQ[a] < RMQ[b]?a:b; 98 } 99 100 int lcp(int a, int b){ 101 a = rk[a]; b = rk[b]; 102 if(a > b) swap(a, b); 103 return height[askRMQ(a + 1, b)]; 104 } 105 106 int main(){ 107 //freopen("data.in","r",stdin); 108 //freopen("data.out","w",stdout); 109 //cin.sync_with_stdio(false); 110 int cs = 0; 111 while(scanf("%s", s) != EOF && s[0] != '#'){ 112 cs++; 113 int n = strlen(s); 114 for(int i = 0; i < n; ++i) r[i] = s[i]; 115 r[n] = 0; 116 da(r, sa, rk, height, n, 200); 117 for(int i = 0; i <= n; ++i) RMQ[i] = height[i]; 118 initRMQ(n); 119 int ans = 0; 120 int tn = n << 1; 121 int arr[maxn],a, ret, t, re = 0,sl; 122 for(int l = 1; l <= tn; ++l){ 123 for(int j = 0; j - l < n; j += l){ 124 sl = lcp(j, j + l); 125 ret = sl / l + 1; 126 t = l - sl%l; 127 t = j - t; 128 if(t>= 0&&sl%l){ 129 if(lcp(t, t + l) >= l) ret++; 130 } 131 if(re < ret){ 132 re = ret; 133 a = 0; 134 arr[a++] = l; // 将重复次数最大的l都存入arr数组中, 最后在一个个枚举,选择最大值 135 }else if(re == ret){ 136 arr[a++] = l; 137 } 138 } 139 } 140 int ansl = 0, ansi = sa[n]; 141 for(int i = 0; i < a; ++i){ 142 for(int j = 0; j + arr[i] < n; ++j){ 143 if(lcp(j, j + arr[i]) / arr[i] + 1 == re){ 144 if(rk[ansi] > rk[j]){ 145 ansi = j; 146 ansl = arr[i]; 147 } 148 } 149 } 150 } 151 if(debug){ 152 dg(ansl); 153 dg(ansi); 154 dg(re); 155 } 156 printf("Case %d: ", cs); 157 for(int i = ansi; i <ansi + ansl * re ; ++i){ 158 printf("%c",s[i]); 159 } 160 printf("\n"); 161 } 162 return 0; 163 }
4.求字符串的循环节的最大循环次数(用dc3,如果 kmp 也可以
1 /* 2 ***********Good LUCK********** 3 * Author: yeahpeng 4 * Created Time: 2015/4/23 23:04:43 5 * File Name: poj2406 6 */ 7 #define _CRT_SECURE_NO_WARNINGS 8 #include <stdio.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <sstream> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <limits.h> 15 #include <vector> 16 #include <string> 17 #include <time.h> 18 #include <math.h> 19 #include <queue> 20 #include <stack> 21 #include <set> 22 #include <map> 23 #define INF 0x3f3f3f3f 24 #define Zero(x) memset((x),0, sizeof(x)) 25 #define Neg(x) memset((x), -1, sizeof(x)) 26 #define dg(x) cout << #x << " = " << x << endl 27 #define pk(x) push_back(x) 28 #define pok() pop_back() 29 #define eps 1e-8 30 #define pii pair<int, int> 31 #define pi acos(-1.0) 32 using namespace std; 33 typedef long long ll; 34 bool debug = false; 35 int OK = 1; 36 const int maxn = 1000100; 37 #define F(x) ((x/3) + ((x) % 3 == 1? 0 : tb)) 38 #define G(x) ((x)<tb?(x)*3 + 1:((x)-tb)*3 + 2) 39 int wa[maxn * 3], wb[maxn * 3], wv[maxn * 3], wss[maxn * 3], sa[maxn * 3], rk[maxn * 3]; 40 int c0(int *r, int a, int b){ 41 return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2]; 42 } 43 44 int c12(int k, int *r, int a, int b){ 45 if (k == 2) 46 return r[a] < r[b] || (r[a] == r[b] && c12(1, r, a + 1, b + 1)); 47 else return r[a] < r[b] || (r[a] == r[b] && wv[a + 1] < wv[b + 1]); 48 } 49 50 void sort(int *r, int *a, int *b, int n, int m){ 51 int i; 52 for (i = 0; i < n; ++i) wv[i] = r[a[i]]; 53 for (i = 0; i < m; ++i) wss[i] = 0; 54 for (i = 0; i < n; ++i) wss[wv[i]]++; 55 for (i = 1; i < m; ++i) wss[i] += wss[i - 1]; 56 for (i = n - 1; i >= 0; --i) 57 b[--wss[wv[i]]] = a[i]; 58 } 59 60 void dc3(int * r, int *sa, int n, int m){ 61 int i, j, *rn = r + n; 62 int *san = sa + n, ta = 0, tb = (n + 1) / 3, tbc = 0, p; 63 r[n] = r[n + 1] = 0; 64 for (i = 0; i < n; ++i) if (i % 3 != 0) wa[tbc++] = i; 65 sort(r + 2, wa, wb, tbc, m); 66 sort(r + 1, wb, wa, tbc, m); 67 sort(r, wa, wb, tbc, m); 68 for (p = 1, rn[F(wb[0])] = 0, i = 1; i < tbc; ++i) 69 rn[F(wb[i])] = c0(r, wb[i - 1], wb[i]) ? p - 1 : p++; 70 if (p < tbc) dc3(rn, san, tbc, p); 71 else for (i = 0; i < tbc; i++) san[rn[i]] = i; 72 for (i = 0; i <tbc; i++) if (san[i] < tb) wb[ta++] = san[i] * 3; 73 if (n % 3 == 1) wb[ta++] = n - 1; 74 sort(r, wb, wa, ta, m); 75 for (i = 0; i < tbc; i++) wv[wb[i] = G(san[i])] = i; 76 for (i = 0, j = 0, p = 0; i < ta && j < tbc; p++) 77 sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++]; 78 for (; i < ta; p++) sa[p] = wa[i++]; 79 for (; j < tbc; p++) sa[p] = wb[j++]; 80 } 81 82 void da(int str[], int sa[], int rk[], int height[], int n, int m){ 83 for (int i = n; i < n + 3; i++) 84 str[i] = 0; 85 dc3(str, sa, n + 1, m); 86 int i, j, k = 0; 87 for (i = 0; i <= n; i++) rk[sa[i]] = i; 88 for (i = 0; i < n; ++i){ 89 if (k) k--; 90 j = sa[rk[i] - 1]; 91 while (str[i + k] == str[j + k]) k++; 92 height[rk[i]] = k; 93 } 94 } 95 char s[maxn]; 96 int n; 97 int r[maxn * 3], height[maxn]; 98 int main(){ 99 //freopen("data.in","r",stdin); 100 //freopen("data.out","w",stdout); 101 //cin.sync_with_stdio(false); 102 while (scanf("%s", s) != EOF){ 103 if (s[0] == '.') break; 104 n = strlen(s); 105 for (int i = 0; i < n; ++i) r[i] = s[i]; 106 r[n] = 0; 107 da(r, sa, rk, height, n, 200); 108 if (debug){ 109 for (int i = 0; i < n; ++i) 110 cout << rk[i] << " "; 111 cout << endl; 112 for (int i = 2; i <= n; ++i) 113 cout << height[i] << " "; 114 cout << endl; 115 } 116 for (int i = 1; i <= n; ++i){ 117 if (n % i == 0){ 118 int from = rk[i], to = rk[0]; 119 if (debug){ 120 dg(from); 121 dg(to); 122 } 123 if (from > to) swap(from, to); // 判断sufffix(0) 和 sufficx(k)的公共前缀是否等于 n - k 124 if (n == i || height[to] == n - i){ 125 printf("%d\n", n / i); 126 break; 127 } 128 } 129 } 130 } 131 return 0; 132 }
5.字符串中不同子串的个数
1 /* 2 ***********Good LUCK********** 3 * Author: yeahpeng 4 * Created Time: 2015/4/23 19:35:41 5 * File Name: spoj705.cpp 6 */ 7 #include <stdio.h> 8 #include <iostream> 9 #include <algorithm> 10 #include <sstream> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <limits.h> 14 #include <vector> 15 #include <string> 16 #include <time.h> 17 #include <math.h> 18 #include <queue> 19 #include <stack> 20 #include <set> 21 #include <map> 22 #define INF 0x3f3f3f3f 23 #define Zero(x) memset((x),0, sizeof(x)) 24 #define Neg(x) memset((x), -1, sizeof(x)) 25 #define dg(x) cout << #x << " = " << x << endl 26 #define pk(x) push_back(x) 27 #define pok() pop_back() 28 #define eps 1e-8 29 #define pii pair<int, int> 30 #define pi acos(-1.0) 31 using namespace std; 32 typedef long long ll; 33 bool debug = false; 34 const int maxn = 50500; 35 int OK = 1; 36 char s[maxn]; 37 int r[maxn], sa[maxn], rk[maxn], t1[maxn], t2[maxn]; 38 int c[maxn], height[maxn]; 39 int n; 40 41 bool cmp(int *r, int a,int b, int l){ 42 return r[a] == r[b] && r[a + l] == r[b + l]; 43 } 44 45 void da(int str[], int sa[], int rk[], int height[], int n, int m){ 46 n++; 47 int i, j, p, *x = t1, *y = t2; 48 for(i = 0; i < m; i++) c[i] = 0; 49 for(i = 0; i < n; ++i) c[x[i] = str[i]]++; 50 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 51 for(i = n - 1; i >= 0; --i) sa[--c[x[i]]] = i; 52 for(j = 1; j <= n; j <<= 1){ 53 p = 0; 54 for(i = n - j; i < n; ++i) y[p++] = i; 55 for(i = 0; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; 56 for(i = 0; i < m; ++i) c[i] = 0; 57 for(i = 0; i < n; ++i) c[x[y[i]]]++; 58 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 59 for(i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i]; 60 swap(x, y); 61 p = 1; x[sa[0]] = 0; 62 for(i = 1; i < n; ++i) 63 x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1: p++; 64 if(p >= n) break; 65 m = p; 66 } 67 int k = 0; 68 n--; 69 for(i = 0; i <= n; ++i) rk[sa[i]] = i; 70 for(i = 0; i <n ; ++i){ 71 if(k) k--; 72 j = sa[rk[i] - 1]; 73 while(str[i + k] == str[j + k]) ++k; 74 height[rk[i]] = k; 75 } 76 } 77 78 int main(){ 79 //freopen("data.in","r",stdin); 80 //freopen("data.out","w",stdout); 81 //cin.sync_with_stdio(false); 82 int T; 83 scanf("%d", &T); 84 for(int i = 0; i < T; ++i){ 85 scanf("%s", s); 86 n = strlen(s); 87 for(int i = 0; i < n; ++i) r[i] = s[i]; 88 r[n] = 0; 89 da(r, sa,rk, height, n, 200); 90 int ans = 0; 91 if(debug){ 92 for(int i = 0; i <= n; ++i) 93 cout << height[i] << " "; 94 cout << endl; 95 for(int i = 1; i <= n; ++i) 96 cout << sa[i] << " "; 97 cout << endl; 98 } 99 ans += n - sa[1]; 100 101 height[n + 1] = 0; 102 for(int i = 2; i <= n; ++i){ 103 ans += n - sa[i] - height[i]; 104 if(debug){ 105 dg(n - sa[i]); 106 dg(sa[i]); 107 dg(height[i]); 108 dg(ans); 109 } 110 } 111 printf("%d\n", ans); 112 } 113 return 0; 114 }
6.重复次数最多的连续重复子串
1 /* 2 ***********Good LUCK********** 3 * Author: yeahpeng 4 * Created Time: 2015/4/24 21:44:34 5 * File Name: poj3693.cpp 6 */ 7 #include <stdio.h> 8 #include <iostream> 9 #include <algorithm> 10 #include <sstream> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <limits.h> 14 #include <vector> 15 #include <string> 16 #include <time.h> 17 #include <math.h> 18 #include <queue> 19 #include <stack> 20 #include <set> 21 #include <map> 22 #define INF 0x3f3f3f3f 23 #define Zero(x) memset((x),0, sizeof(x)) 24 #define Neg(x) memset((x), -1, sizeof(x)) 25 #define dg(x) cout << #x << " = " << x << endl 26 #define pk(x) push_back(x) 27 #define pok() pop_back() 28 #define eps 1e-8 29 #define pii pair<int, int> 30 #define pi acos(-1.0) 31 using namespace std; 32 typedef long long ll; 33 bool debug = false; 34 int OK = 1; 35 const int maxn = 100100; 36 char s[maxn]; 37 int t1[maxn], t2[maxn], c[maxn]; 38 bool cmp(int *r, int a,int b, int l){ 39 return r[a] == r[b] && r[a + l] == r[b + l]; 40 } 41 42 void da(int str[], int sa[], int rk[], int height[], int n, int m){ 43 n++; 44 int i, j, p, *x = t1, *y = t2; 45 for(i = 0; i < m; i++) c[i] = 0; 46 for(i = 0; i < n; ++i) c[x[i] = str[i]]++; 47 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 48 for(i = n - 1; i >= 0; --i) sa[--c[x[i]]] = i; 49 for(j = 1; j <= n; j <<= 1){ 50 p = 0; 51 for(i = n - j; i < n; ++i) y[p++] = i; 52 for(i = 0; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; 53 for(i = 0; i < m; ++i) c[i] = 0; 54 for(i = 0; i < n; ++i) c[x[y[i]]]++; 55 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 56 for(i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i]; 57 swap(x, y); 58 p = 1; x[sa[0]] = 0; 59 for(i = 1; i < n; ++i) 60 x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1: p++; 61 if(p >= n) break; 62 m = p; 63 } 64 int k = 0; 65 n--; 66 for(i = 0; i <= n; ++i) rk[sa[i]] = i; 67 for(i = 0; i <n ; ++i){ 68 if(k) k--; 69 j = sa[rk[i] - 1]; 70 while(str[i + k] == str[j + k]) ++k; 71 height[rk[i]] = k; 72 } 73 } 74 75 int best[20][maxn], mm[maxn]; 76 int rk[maxn], height[maxn], RMQ[maxn],r[maxn]; 77 int sa[maxn]; 78 void initRMQ(int n){ 79 mm[0] = -1; 80 for(int i = 1; i <= n; ++i) 81 mm[i] = ((i&(i - 1)) == 0)?mm[i-1] + 1:mm[i-1]; 82 for(int i = 1; i <= n; ++i) best[0][i] = i; 83 for(int i = 1; i <= mm[n]; ++i) 84 for(int j = 1; j + (1 <<i) - 1 <= n; ++j){ 85 int a = best[i-1][j]; 86 int b = best[i-1][j+(1 << (i-1))]; 87 if(RMQ[a] < RMQ[b]) best[i][j] = a; 88 else best[i][j] = b; 89 } 90 } 91 92 int askRMQ(int a, int b){ 93 int t; 94 t = mm[b - a + 1]; 95 b -= (1 << t) - 1; 96 a = best[t][a]; b = best[t][b]; 97 return RMQ[a] < RMQ[b]?a:b; 98 } 99 100 int lcp(int a, int b){ 101 a = rk[a]; b = rk[b]; 102 if(a > b) swap(a, b); 103 return height[askRMQ(a + 1, b)]; 104 } 105 106 int main(){ 107 //freopen("data.in","r",stdin); 108 //freopen("data.out","w",stdout); 109 //cin.sync_with_stdio(false); 110 int cs = 0; 111 while(scanf("%s", s) != EOF && s[0] != '#'){ 112 cs++; 113 int n = strlen(s); 114 for(int i = 0; i < n; ++i) r[i] = s[i]; 115 r[n] = 0; 116 da(r, sa, rk, height, n, 200); 117 for(int i = 0; i <= n; ++i) RMQ[i] = height[i]; 118 initRMQ(n); 119 int ans = 0; 120 int tn = n << 1; 121 int arr[maxn],a, ret, t, re = 0,sl; 122 for(int l = 1; l <= tn; ++l){ 123 for(int j = 0; j - l < n; j += l){ 124 sl = lcp(j, j + l); 125 ret = sl / l + 1; 126 t = l - sl%l; 127 t = j - t; 128 if(t>= 0&&sl%l){ 129 if(lcp(t, t + l) >= l) ret++; 130 } 131 if(re < ret){ 132 re = ret; 133 a = 0; 134 arr[a++] = l; // 将重复次数最大的l都存入arr数组中, 最后在一个个枚举,选择最大值 135 }else if(re == ret){ 136 arr[a++] = l; 137 } 138 } 139 } 140 int ansl = 0, ansi = sa[n]; 141 for(int i = 0; i < a; ++i){ 142 for(int j = 0; j + arr[i] < n; ++j){ 143 if(lcp(j, j + arr[i]) / arr[i] + 1 == re){ 144 if(rk[ansi] > rk[j]){ 145 ansi = j; 146 ansl = arr[i]; 147 } 148 } 149 } 150 } 151 if(debug){ 152 dg(ansl); 153 dg(ansi); 154 dg(re); 155 } 156 printf("Case %d: ", cs); 157 for(int i = ansi; i <ansi + ansl * re ; ++i){ 158 printf("%c",s[i]); 159 } 160 printf("\n"); 161 } 162 return 0; 163 }