[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 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 }
原文地址:https://www.cnblogs.com/chenyushuo/p/4124834.html