1717: [Usaco2006 Dec]Milk Patterns 产奶的模式
Time Limit: 5 Sec
Memory Limit: 64 MB
Submit: 1064
Solved: 580
题解:
后缀数组求出来Height数组,然后求出相邻的K个串的LCP即可,不需要让串的长度大于K,因为等于K一定比大于K更优,单调队列维护连续k-1个height里的最小值(因为k-1个height相当于k的串的LCP)。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
const int N=200010;
using namespace std;
int n,k;
int m,p,wa[N],wb[N],SA[N],RK[N],HE[N],c[N],cnt,q[N],ans;
char s[N];
void GetSA()
{
int *x=wa,*y=wb;
m=255,p=0;
for (int i=1;i<=n;i++) c[x[i]=s[i]]++;
for (int i=1;i<=m;i++) c[i]+=c[i-1];
for (int i=n;i>=1;i--) SA[c[x[i]]--]=i;
for (int k=1;p<n;k<<=1)
{
p=0;
for(int i=n-k+1;i<=n;i++) y[++p]=i;
for(int i=1;i<=n;i++)
if(SA[i]>k) y[++p]=SA[i]-k;
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++) c[x[y[i]]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i>=1;i--) SA[c[x[y[i]]]--]=y[i];
swap(x,y);
p=1;
x[SA[1]]=p;
for(int i=2;i<=n;i++)
{
if(y[SA[i]]!=y[SA[i-1]]||y[SA[i]+k]!=y[SA[i-1]+k]) p++;
x[SA[i]]=p;
}
m=p;
}
}
void GetRK()
{
for(int i=1;i<=n;i++) RK[SA[i]]=i;
}
void GetHE()
{
int j=0;
for(int i=1;i<=n;i++)
{
if(RK[i]==1) continue;
while(s[i+j]==s[SA[RK[i]-1]+j]) j++;
HE[RK[i]]=j;
if(j) j--;
}
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&s[i]);
GetSA(),GetRK(),GetHE();
int h=1,t=0;
k--;
for(int i=1;i<=n;i++)
{
while(h<=t&&q[h]<=i-k) h++;
while(h<=t&&HE[i]<HE[q[t]]) t--;
q[++t]=i;
if(i>=k) ans=max(ans,HE[q[h]]);
}
printf("%d",ans);
}
Description
农夫John发现他的奶牛产奶的质量一直在变动。经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠。我们称之为一个“模式”。 John的牛奶按质量可以被赋予一个0到1000000之间的数。并且John记录了N(1<=N<=20000)天的牛奶质量值。他想知道最长的出现了至少K(2<=K<=N)次的模式的长度。比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次。当K=2时,这个长度为4。
Input
* Line 1: 两个整数 N,K。
* Lines 2..N+1: 每行一个整数表示当天的质量值。
Output
* Line 1: 一个整数:N天中最长的出现了至少K次的模式的长度
Sample Input
8 2
1
2
3
2
3
2
3
1
1
2
3
2
3
2
3
1
Sample Output
4