POJ3261(SummerTrainingDay10-G 后缀数组)
Milk Patterns
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 15974 | Accepted: 7041 | |
Case Time Limit: 2000MS |
Description
Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.
To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns -- 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.
Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.
Input
Lines 2..N+1: N integers, one per line, the quality of the milk on day i appears on the ith line.
Output
Sample Input
8 2 1 2 3 2 3 2 3 1
Sample Output
4
Source
1 //2017-08-11 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 7 using namespace std; 8 9 const int N = 1000010; 10 const int inf = 0x3f3f3f3f; 11 char str[N]; 12 int n, r[N], k; 13 int wa[N], wb[N], wv[N], wss[N]; 14 int Suffix[N];//Str下标为i ~ Len的连续子串(即后缀) 15 int SA[N];//满足Suffix[SA[1]] < Suffix[SA[2]] …… < Suffix[SA[Len]],即排名为i的后缀为Suffix[SA[i]](与Rank是互逆运算) 16 int Rank[N];//Suffix[i]在所有后缀中的排名 17 int Height[N];//height[i]表示Suffix[SA[i]]和Suffix[SA[i-1]]的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀 18 int H[N];//等于Height[Rank[i]],也就是后缀Suffix[i]和它前一名的后缀的最长公共前缀 19 20 //比较母串r中起始位置为a和b,长度都为len的子串是否相等 21 int cmp(int *r, int a, int b, int len) 22 { 23 return r[a]==r[b] && r[a+len]==r[b+len]; 24 } 25 26 //倍增算法求SA数组。 27 void da(int *r, int *SA, int n, int m) 28 { 29 int i, j, p, *x = wa, *y = wb, *t; 30 for(i = 0; i < m; i++)wss[i] = 0; 31 for(i = 0; i < n; i++)wss[x[i]=r[i]]++; 32 for(i = 0; i < m; i++)wss[i]+=wss[i-1]; 33 for(i = n-1; i >= 0; i--)SA[--wss[x[i]]]=i; 34 for(j = 1, p = 1; p < n; j *= 2, m = p){ 35 for(p = 0, i = n-j; i < n; i++) 36 y[p++] = i; 37 for(i = 0; i < n; i++) 38 if(SA[i] >= j) 39 y[p++] = SA[i]-j; 40 for(i = 0; i < n; i++) 41 wv[i] = x[y[i]]; 42 for(i = 0; i < m; i++) 43 wss[i] = 0; 44 for(i = 0; i < n; i++) 45 wss[wv[i]]++; 46 for(i = 1; i < m; i++) 47 wss[i] += wss[i-1]; 48 for(i = n-1; i >= 0; i--) 49 SA[--wss[wv[i]]] = y[i]; 50 for(t = x, x = y, y = t, p = 1, x[SA[0]]=0, i = 1; i < n; i++) 51 x[SA[i]] = cmp(y, SA[i-1], SA[i], j)?p-1:p++; 52 } 53 } 54 55 //计算height数组 56 void cal_Height(int *r, int *SA, int n) 57 { 58 int i, j, k = 0; 59 for(i = 1; i <= n; i++)Rank[SA[i]] = i; 60 for(i = 0; i < n; Height[Rank[i++]] = k) 61 for(k?k--:0, j=SA[Rank[i]-1]; r[i+k]==r[j+k]; k++) 62 ; 63 } 64 65 int st[N][30]; 66 67 void init_rmq(int n) 68 { 69 for(int i=1;i<=n;i++) st[i][0]=Height[i]; 70 for(int j=1;(1<<j)<=n;j++) 71 for(int i=1;i+(1<<j)-1<=n;i++) 72 { 73 st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); 74 } 75 } 76 77 //询问后缀i和后缀j的最长公共前缀 78 int lcp(int i,int j) 79 { 80 i = Rank[i]; 81 j = Rank[j]; 82 if(i>j) swap(i,j); 83 i++; 84 int k=0; 85 while(i+(1<<(k+1)) <= j) k++; 86 return min(st[i][k],st[j-(1<<k)+1][k]); 87 } 88 89 bool check(int len){ 90 int cnt = 1; 91 for(int i = 1; i <= n; i++){ 92 if(Height[i] >= len){//将Height进行分组,每组内Height值均大于k。 93 cnt++; 94 }else cnt = 1;//重新分组 95 if(cnt >= k)return true;//一组内元素个数不小于k,说明存在 96 } 97 return false; 98 } 99 100 int main() 101 { 102 while(scanf("%d%d", &n, &k)!=EOF) 103 { 104 for(int i = 0; i < n; i++) 105 scanf("%d", &r[i]); 106 da(r, SA, n+1, 1000010); 107 cal_Height(r, SA, n); 108 //二分答案,进行判定 109 int l = 1, r = n, mid, ans = 0; 110 while(l <= r){ 111 mid = (l+r)/2; 112 if(check(mid)){ 113 ans = mid; 114 l = mid+1; 115 }else r = mid-1; 116 } 117 printf("%d\n", ans); 118 } 119 120 return 0; 121 }