SPOJ - REPEATS —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/SPOJ-REPEATS
REPEATS - Repeats
A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed string t with length l>=1. For example, the string
s = abaabaabaaba
is a (4,3)-repeat with t = aba as its seed string. That is, the seed string t is 3 characters long, and the whole string s is obtained by repeating t 4 times.
Write a program for the following task: Your program is given a long string u consisting of characters ‘a’ and/or ‘b’ as input. Your program must find some (k,l)-repeat that occurs as substring within u with k as large as possible. For example, the input string
u = babbabaabaabaabab
contains the underlined (4,3)-repeat s starting at position 5. Since u contains no other contiguous substring with more than 4 repeats, your program must output the maximum k.
Input
In the first line of the input contains H- the number of test cases (H <= 20). H test cases follow. First line of each test cases is n - length of the input string (n <= 50000), The next n lines contain the input string, one character (either ‘a’ or ‘b’) per line, in order.
Output
For each test cases, you should write exactly one interger k in a line - the repeat count that is maximized.
Example
Input: 1 17 b a b b a b a a b a a b a a b a b Output: 4since a (4, 3)-repeat is found starting at the 5th character of the input string.
题意:
给出一个字符串,求该字符串的重复次数最多的连续重复子串,输出重复次数。
题解:
论文上面的题。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 5e4+100; 18 19 bool cmp(int *r, int a, int b, int l) 20 { 21 return r[a]==r[b] && r[a+l]==r[b+l]; 22 } 23 24 int r[MAXN], sa[MAXN], Rank[MAXN], height[MAXN]; 25 int t1[MAXN], t2[MAXN], c[MAXN]; 26 void DA(int str[], int sa[], int Rank[], int height[], int n, int m) 27 { 28 n++; 29 int i, j, p, *x = t1, *y = t2; 30 for(i = 0; i<m; i++) c[i] = 0; 31 for(i = 0; i<n; i++) c[x[i] = str[i]]++; 32 for(i = 1; i<m; i++) c[i] += c[i-1]; 33 for(i = n-1; i>=0; i--) sa[--c[x[i]]] = i; 34 for(j = 1; j<=n; j <<= 1) 35 { 36 p = 0; 37 for(i = n-j; i<n; i++) y[p++] = i; 38 for(i = 0; i<n; i++) if(sa[i]>=j) y[p++] = sa[i]-j; 39 40 for(i = 0; i<m; i++) c[i] = 0; 41 for(i = 0; i<n; i++) c[x[y[i]]]++; 42 for(i = 1; i<m; i++) c[i] += c[i-1]; 43 for(i = n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i]; 44 45 swap(x, y); 46 p = 1; x[sa[0]] = 0; 47 for(i = 1; i<n; i++) 48 x[sa[i]] = cmp(y, sa[i-1], sa[i], j)?p-1:p++; 49 50 if(p>=n) break; 51 m = p; 52 } 53 54 int k = 0; 55 n--; 56 for(i = 0; i<=n; i++) Rank[sa[i]] = i; 57 for(i = 0; i<n; i++) 58 { 59 if(k) k--; 60 j = sa[Rank[i]-1]; 61 while(str[i+k]==str[j+k]) k++; 62 height[Rank[i]] = k; 63 } 64 } 65 66 int dp[MAXN][20], mm[MAXN]; 67 void initRMQ(int n, int b[]) 68 { 69 mm[0] = -1; 70 for(int i = 1; i<=n; i++) 71 dp[i][0] = b[i], mm[i] = ((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; 72 for(int j = 1; j<=mm[n]; j++) 73 for(int i = 1; i+(1<<j)-1<=n; i++) 74 dp[i][j] = min(dp[i][j-1], dp[i+(1<<(j-1))][j-1]); 75 } 76 77 int RMQ(int x, int y) 78 { 79 if(x>y) swap(x, y); 80 x++; 81 int k = mm[y-x+1]; 82 return min(dp[x][k], dp[y-(1<<k)+1][k]); 83 } 84 85 int main() 86 { 87 int T, n; 88 scanf("%d", &T); 89 while(T--) 90 { 91 scanf("%d", &n); 92 for(int i = 0; i<n; i++) 93 { 94 char ch; 95 getchar(); 96 scanf("%c", &ch); 97 r[i] = ch-'a'+1; 98 } 99 r[n] = 0; 100 DA(r, sa, Rank, height, n, 3); 101 initRMQ(n, height); 102 103 int times = 0, L, R; 104 for(int len = 1; len<=n; len++) 105 for(int pos = 0; pos+len<n; pos += len) 106 { 107 int LCP = RMQ(Rank[pos], Rank[pos+len]); 108 int supplement = len - LCP%len; 109 int k = pos - supplement; 110 if(k>=0 && LCP%len && RMQ(Rank[k],Rank[k+len])>=supplement) 111 LCP += supplement; 112 times = max(times, LCP/len+1); 113 } 114 printf("%d\n", times); 115 } 116 }