POJ 3261 Milk Patterns(后缀数组+单调队列)

题意

找出出现k次的可重叠的最长子串的长度

题解

用后缀数组。

然后求出heigth数组。

跑单调队列就行了。找出每k个数中最小的数的最大值。就是个滑动窗口啊

(不知道为什么有人写二分,其实写啥都差不多快,可能是因为二分是一个常见的模型吧)

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=1000100;
 8 int n,m,x[N],sa[N],c[N],k,height[N],rk[N],y[N],ans,q[N],head,tail,s[N];
 9 void get_sa(){
10     for(int i=1;i<=n;i++)c[x[i]=s[i]]++;
11     for(int i=1;i<=m;i++)c[i]+=c[i-1];
12     for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;
13     for(int k=1;k<=n;k<<=1){
14         int num=0;
15         for(int i=n-k+1;i<=n;i++)y[++num]=i;
16         for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;
17         for(int i=1;i<=m;i++)c[i]=0;
18         for(int i=1;i<=n;i++)c[x[i]]++;
19         for(int i=1;i<=m;i++)c[i]+=c[i-1];
20         for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0;
21         for(int i=1;i<=n;i++){
22             swap(x[i],y[i]);
23         }
24         x[sa[1]]=1;num=1;
25         for(int i=2;i<=n;i++){
26             x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
27         } 
28         if(n==num)break;
29         m=num;
30     }
31 }
32 void get_height(){
33     for(int i=1;i<=n;i++)rk[sa[i]]=i;
34     int k=0;
35     for(int i=1;i<=n;i++){
36         if(rk[i]==1)continue;
37         if(k)k--;
38         int j=sa[rk[i]-1];
39         while(j+k<=n&&i+k<=n&&s[j+k]==s[i+k])k++;
40         height[rk[i]]=k;
41     }
42 }
43 int main(){
44     scanf("%d%d",&n,&k);
45     if(k==1){
46         printf("%d",n);
47         return 0;
48     }
49     m=1000005;
50     for(int i=1;i<=n;i++){
51         scanf("%d",&s[i]);
52     }
53     get_sa();
54     get_height();
55     head=1;tail=0;
56     for(int i=2;i<=k;i++){
57         while(height[i]<=height[q[tail]]&&head<=tail)tail--;
58         q[++tail]=i;
59     }
60     ans=height[q[head]];
61     for(int i=k+1;i<=n;i++){
62         while(q[head]<=i-k+1&&head<=tail)head++;
63         while(height[i]<=height[q[tail]]&&head<=tail)tail--;
64         q[++tail]=i;
65         ans=max(ans,height[q[head]]);
66     }
67     printf("%d",ans);
68     return 0;
69 }

猜你喜欢

转载自www.cnblogs.com/Xu-daxia/p/9636883.html