首页 > 代码库 > [Usaco2006 Dec]Milk Patterns

[Usaco2006 Dec]Milk Patterns

[Usaco2006 Dec]Milk Patterns

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 212323231

 

Sample Output

 

4

 

Source

后缀数组

 

答案应该是height数组中连续K-1个值的最小值的最大值。

这题还是要先离散化一下,不然可能会MLE

 

#include<cstdio>#include<cstring>#include<algorithm>#define maxn 30010using namespace std;char ch;int n,k,max_val,tot,head,tail,s[maxn],num[maxn],SA[maxn],rank[maxn],tmp[maxn],sum[maxn],height[maxn];struct DATA{	int val,tim;}list[maxn];inline bool isdigit(char ch){return ‘0‘<=ch&&ch<=‘9‘;}inline void read(int &x){	for (ch=getchar();!isdigit(ch);ch=getchar());	for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());}inline bool cmp(int a,int b){return s[a]<s[b];}void prepare(){	sort(num+1,num+1+n,cmp);	for (int i=1,pre=-1;i<=n;i++){		if (s[num[i]]!=pre) pre=s[num[i]],++max_val;		s[num[i]]=max_val;	}}void get_SA(){	for (int i=1;i<=n;i++) sum[tmp[i]=s[i]]++;	for (int i=1;i<=max_val;i++) sum[i]+=sum[i-1];	for (int i=n;i>=1;i--) SA[sum[tmp[i]]--]=i;	rank[SA[1]]=tot=1;	for (int i=2;i<=n;i++){		if (tmp[SA[i]]!=tmp[SA[i-1]]) tot++;		rank[SA[i]]=tot;		}	for (int len=1;len<=n;len<<=1){		memset(sum,0,sizeof(sum));		for (int i=1;i<=n;i++) sum[rank[i+len]]++;		for (int i=1;i<=n;i++) sum[i]+=sum[i-1];		for (int i=n;i>=1;i--) tmp[sum[rank[i+len]]--]=i;		memset(sum,0,sizeof(sum));		for (int i=1;i<=n;i++) sum[rank[tmp[i]]]++;		for (int i=1;i<=n;i++) sum[i]+=sum[i-1];		for (int i=n;i>=1;i--) SA[sum[rank[tmp[i]]]--]=tmp[i];		tmp[SA[1]]=tot=1;		for (int i=2;i<=n;i++){			if (rank[SA[i]]!=rank[SA[i-1]]||rank[SA[i]+len]!=rank[SA[i-1]+len]) tot++;			tmp[SA[i]]=tot;			}		for (int i=1;i<=n;i++) rank[i]=tmp[i];			}}void get_height(){	for (int i=1,j=0;i<=n;i++){		if (rank[i]==1) continue;		while (s[i+j]==s[SA[rank[i]-1]+j]) j++;			height[rank[i]]=j;		if (j>0) j--;	}}int main(){	read(n),read(k);	for (int i=1;i<=n;i++) read(s[i]),num[i]=i;	prepare(),get_SA(),get_height();	k--,head=1,tail=0,max_val=0;	for (int i=2;i<=n;i++){		while (head<=tail&&i-list[head].tim>=k) head++;		while (head<=tail&&height[i]<list[tail].val) tail--;		list[++tail]=(DATA){height[i],i};		if (i>k&&max_val<list[head].val) max_val=list[head].val;	}	printf("%d\n",max_val);	return 0;	}

[Usaco2006 Dec]Milk Patterns