POJ3261 Milk Patterns(二分+后缀数组)
题目求最长的重复k次可重叠子串。
与POJ1743同理。
- 二分枚举ans判定是否成立
- height分组,如果大于等于ans的组里的个数大于等于k-1,这个ans就可行
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define MAXN 1000001 6 7 int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN]; 8 int cmp(int *r,int a,int b,int l){ 9 return r[a]==r[b] && r[a+l]==r[b+l]; 10 } 11 int sa[MAXN],rank[MAXN],height[MAXN]; 12 void SA(int *r,int n,int m){ 13 int *x=wa,*y=wb; 14 15 for(int i=0; i<m; ++i) ws[i]=0; 16 for(int i=0; i<n; ++i) ++ws[x[i]=r[i]]; 17 for(int i=1; i<m; ++i) ws[i]+=ws[i-1]; 18 for(int i=n-1; i>=0; --i) sa[--ws[x[i]]]=i; 19 20 int p=1; 21 for(int j=1; p<n; j<<=1,m=p){ 22 p=0; 23 for(int i=n-j; i<n; ++i) y[p++]=i; 24 for(int i=0; i<n; ++i) if(sa[i]>=j) y[p++]=sa[i]-j; 25 for(int i=0; i<n; ++i) wv[i]=x[y[i]]; 26 for(int i=0; i<m; ++i) ws[i]=0; 27 for(int i=0; i<n; ++i) ++ws[wv[i]]; 28 for(int i=1; i<m; ++i) ws[i]+=ws[i-1]; 29 for(int i=n-1; i>=0; --i) sa[--ws[wv[i]]]=y[i]; 30 swap(x,y); x[sa[0]]=0; p=1; 31 for(int i=1; i<n; ++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 32 } 33 34 for(int i=1; i<n; ++i) rank[sa[i]]=i; 35 int k=0; 36 for(int i=0; i<n-1; height[rank[i++]]=k){ 37 if(k) --k; 38 for(int j=sa[rank[i]-1]; r[i+k]==r[j+k]; ++k); 39 } 40 } 41 42 int n,k,a[MAXN]; 43 bool isok(int len){ 44 int cnt=0; 45 bool flag=0; 46 for(int i=2; i<=n; ++i){ 47 if(height[i]>=len){ 48 if(flag){ 49 ++cnt; 50 if(cnt+1>=k) return 1; 51 }else{ 52 flag=1; 53 cnt=1; 54 if(cnt+1>=k) return 1; 55 } 56 }else{ 57 flag=0; 58 cnt=0; 59 } 60 } 61 return 0; 62 } 63 int main(){ 64 int mx=0; 65 scanf("%d%d",&n,&k); 66 for(int i=0; i<n; ++i){ 67 scanf("%d",a+i); 68 mx=max(mx,++a[i]); 69 } 70 a[n]=0; 71 SA(a,n+1,mx+1); 72 int l=0,r=n; 73 while(l<r){ 74 int mid=l+r+1>>1; 75 if(isok(mid)) l=mid; 76 else r=mid-1; 77 } 78 printf("%d",l); 79 return 0; 80 }