POJ 1743-Musical Theme-后缀数组
Posted Helica
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1743-Musical Theme-后缀数组相关的知识,希望对你有一定的参考价值。
论文上讲的很清楚。
最长不重叠重复子串问题。首先二分答案,对于每一个mid长度,按照后缀的height大于mid对height数组分组。
可以证明,答案在同一个height当中。维护每一组的最大最小sa值,差便是每一组的最大不重叠重复子串长度。如果大于mid就return true。
看代码很容易懂
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 7 const int maxn = 2e4+10; 8 int N,save[maxn]; 9 10 int s[maxn]; 11 int sa[maxn],t[maxn],t2[maxn],c[maxn]; 12 int rank[maxn],height[maxn]; 13 14 void Build(int n,int m) 15 { 16 int i,j,*x = t,*y = t2; 17 for(i=0;i<m;i++) c[i] = 0; 18 for(i=0;i<n;i++) c[x[i]=s[i] ] ++; 19 for(i=1;i<m;i++) c[i] += c[i-1]; 20 for(i=n-1;i>=0;i--) sa[--c[x[i] ] ] = i; 21 22 for(int k=1;k<=n;k<<=1) 23 { 24 int p = 0; 25 for(i=n-k;i<n;i++) y[p++] = i; 26 for(i=0;i<n;i++) if(sa[i]>=k) y[p++] = sa[i]-k; 27 28 for(i=0;i<m;i++) c[i] = 0; 29 for(i=0;i<n;i++) c[x[y[i] ] ]++; 30 for(i=1;i<m;i++) c[i] += c[i-1]; 31 for(i=n-1;i>=0;i--) sa[--c[x[y[i] ] ] ] = y[i]; 32 33 swap(x,y); 34 p = 1;x[sa[0] ] = 0; 35 for(i=1;i<n;i++) 36 x[sa[i] ] = y[sa[i-1] ]==y[sa[i] ]&&y[sa[i-1]+k ]==y[sa[i]+k ]?p-1:p++; 37 if(p>=n) break; 38 m = p; 39 } 40 n--; 41 42 int k=0; 43 for(i=0;i<=n;i++) rank[sa[i]] = i; 44 for(i=0;i<n;i++) 45 { 46 if(k) k--; 47 j = sa[rank[i]-1 ]; 48 while(s[i+k]==s[j+k]) k++; 49 height[rank[i] ] = k; 50 } 51 } 52 53 bool check(int k,int n) 54 { 55 int mx=sa[1],mi=sa[1]; 56 for(int i=2;i<=n;i++) 57 { 58 if(height[i] < k) 59 { 60 mx = mi = sa[i]; 61 } 62 else 63 { 64 if(sa[i] > mx) mx = sa[i]; 65 if(sa[i] < mi) mi = sa[i]; 66 if(mx-mi > k) return true; 67 } 68 } 69 return false; 70 } 71 72 int main() 73 { 74 while(scanf("%d",&N) && N) 75 { 76 for(int i=0;i<N;i++) 77 scanf("%d",&save[i]); 78 for(int i=N-1;i>0;i--) 79 s[i] = save[i] - save[i-1] + 90; 80 N--; 81 for(int i=0;i<N;i++) s[i] = s[i+1]; 82 s[N] = 0; 83 84 Build(N+1,200); 85 int mid,l=1,r = N; 86 int ans = -1; 87 88 while(l<=r) 89 { 90 mid = (l+r)>>1; 91 if(check(mid,N)) 92 { 93 ans = mid; 94 l = mid+1; 95 } 96 else 97 r = mid-1; 98 } 99 //printf("ans:%d\\n",ans); 100 if(mid < 4) printf("0\\n"); 101 else printf("%d\\n",ans+1); 102 } 103 }
以上是关于POJ 1743-Musical Theme-后缀数组的主要内容,如果未能解决你的问题,请参考以下文章
POJ 1743 Musical Theme(后缀数组[不可重叠最长重复子串])