POJ3261 Milk Patterns(二分+后缀数组)

题目求最长的重复k次可重叠子串。

POJ1743同理。

  1. 二分枚举ans判定是否成立
  2. 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 }

 

posted @ 2016-02-19 15:38  WABoss  阅读(225)  评论(0编辑  收藏  举报