[poj3261]Milk Patterns(后缀数组)
题意:可重叠的k次最长重复子串
解题关键:利用height数组对后缀进行分组,因为最长公共子串一定会在一个组内,所以判定每个组即可。二分答案,进行判定。
1 #include <cstdlib> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include<iostream> 6 #include<cmath> 7 #define inf 0x3f3f3f3f 8 using namespace std; 9 const int N=200005; 10 int wa[N],wb[N],wv[N],wc[N]; 11 bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];} 12 void make_sa(int *r,int *sa,int n,int m){ 13 int i,j,p,*x=wa,*y=wb; 14 for(i=0;i<m;i++) wc[i]=0; 15 for(i=0;i<n;i++) wc[x[i]=r[i]]++; 16 for(i=1;i<m;i++) wc[i]+=wc[i-1]; 17 for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i; 18 for(j=1,p=1;p<n;j*=2,m=p){ 19 for(p=0,i=n-j;i<n;i++) y[p++]=i; 20 for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; 21 for(i=0;i<n;i++) wv[i]=x[y[i]]; 22 for(i=0;i<m;i++) wc[i]=0; 23 for(i=0;i<n;i++) wc[wv[i]]++; 24 for(i=1;i<m;i++) wc[i]+=wc[i-1]; 25 for(i=n-1;i>=0;i--) sa[--wc[wv[i]]]=y[i]; 26 for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 27 } 28 return; 29 } 30 int rank1[N],height[N],sa[N]; 31 void make_height(int *r,int *sa,int n){ 32 int i,j,k=0; 33 for(i=1;i<=n;i++) rank1[sa[i]]=i; 34 for(i=0;i<n;height[rank1[i++]]=k) 35 for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++); 36 return; 37 } 38 39 int n,k,r[N]; 40 bool check(int x){ 41 int num=0; 42 for(int i=2;i<=n;i++){ 43 if(height[i]>=x){ 44 num++; 45 if(num>=k) return true; 46 } 47 else num=1; 48 } 49 return false; 50 } 51 52 int erfen(int l,int r){ 53 while(l<r){ 54 int mid=(l+r+1)>>1; 55 if(check(mid)) l=mid; 56 else r=mid-1; 57 } 58 return l; 59 } 60 61 int main(){ 62 ios::sync_with_stdio(0); 63 int maxn=0; 64 while(cin>>n>>k){ 65 for(int i=0;i<n;i++) cin>>r[i],maxn=max(maxn,r[i]); 66 r[n]=0; 67 make_sa(r, sa, n+1,maxn+1); 68 make_height(r, sa, n); 69 int ans=erfen(0,n); 70 cout<<ans<<"\n"; 71 } 72 return 0; 73 }