[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 }

 

posted @ 2017-09-22 20:05  Elpsywk  阅读(157)  评论(0编辑  收藏  举报