[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 2
1
2
3
2
3
2
3
1
Sample Output
4
Source
后缀数组
答案应该是height数组中连续K-1个值的最小值的最大值。
这题还是要先离散化一下,不然可能会MLE
code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define maxn 30010 5 using namespace std; 6 char ch; 7 int n,k,max_val,tot,head,tail,s[maxn],num[maxn],SA[maxn],rank[maxn],tmp[maxn],sum[maxn],height[maxn]; 8 struct DATA{ 9 int val,tim; 10 }list[maxn]; 11 inline bool isdigit(char ch){return '0'<=ch&&ch<='9';} 12 inline void read(int &x){ 13 for (ch=getchar();!isdigit(ch);ch=getchar()); 14 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 15 } 16 inline bool cmp(int a,int b){return s[a]<s[b];} 17 void prepare(){ 18 sort(num+1,num+1+n,cmp); 19 for (int i=1,pre=-1;i<=n;i++){ 20 if (s[num[i]]!=pre) pre=s[num[i]],++max_val; 21 s[num[i]]=max_val; 22 } 23 } 24 void get_SA(){ 25 for (int i=1;i<=n;i++) sum[tmp[i]=s[i]]++; 26 for (int i=1;i<=max_val;i++) sum[i]+=sum[i-1]; 27 for (int i=n;i>=1;i--) SA[sum[tmp[i]]--]=i; 28 rank[SA[1]]=tot=1; 29 for (int i=2;i<=n;i++){ 30 if (tmp[SA[i]]!=tmp[SA[i-1]]) tot++; 31 rank[SA[i]]=tot; 32 } 33 for (int len=1;len<=n;len<<=1){ 34 memset(sum,0,sizeof(sum)); 35 for (int i=1;i<=n;i++) sum[rank[i+len]]++; 36 for (int i=1;i<=n;i++) sum[i]+=sum[i-1]; 37 for (int i=n;i>=1;i--) tmp[sum[rank[i+len]]--]=i; 38 memset(sum,0,sizeof(sum)); 39 for (int i=1;i<=n;i++) sum[rank[tmp[i]]]++; 40 for (int i=1;i<=n;i++) sum[i]+=sum[i-1]; 41 for (int i=n;i>=1;i--) SA[sum[rank[tmp[i]]]--]=tmp[i]; 42 tmp[SA[1]]=tot=1; 43 for (int i=2;i<=n;i++){ 44 if (rank[SA[i]]!=rank[SA[i-1]]||rank[SA[i]+len]!=rank[SA[i-1]+len]) tot++; 45 tmp[SA[i]]=tot; 46 } 47 for (int i=1;i<=n;i++) rank[i]=tmp[i]; 48 } 49 } 50 void get_height(){ 51 for (int i=1,j=0;i<=n;i++){ 52 if (rank[i]==1) continue; 53 while (s[i+j]==s[SA[rank[i]-1]+j]) j++; 54 height[rank[i]]=j; 55 if (j>0) j--; 56 } 57 } 58 int main(){ 59 read(n),read(k); 60 for (int i=1;i<=n;i++) read(s[i]),num[i]=i; 61 prepare(),get_SA(),get_height(); 62 k--,head=1,tail=0,max_val=0; 63 for (int i=2;i<=n;i++){ 64 while (head<=tail&&i-list[head].tim>=k) head++; 65 while (head<=tail&&height[i]<list[tail].val) tail--; 66 list[++tail]=(DATA){height[i],i}; 67 if (i>k&&max_val<list[head].val) max_val=list[head].val; 68 } 69 printf("%d ",max_val); 70 return 0; 71 }