bzoj1717

[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
 
*******************************************************************************************************************************************

题意:给定长为N的数组,问重复次数不小于K的最长区间长度。

首先,我们应该了解到所有后缀的前缀就是所有的子串。所以,相同子串那么他们的rank[]一定相临。想长度大小就是height[].

所以,height[]中连续连续k个数中最小值最大。所以二分值的大小,依次判断就可以了。

应该用单调队列也可以了,没有试过。

***********************************************************************************************

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=20010;
 4 int s[maxn],sa[maxn],rank[maxn],saf[maxn],cs[maxn],height[maxn];
 5 int n,m,cc,kk;
 6 void init()
 7 {
 8     scanf("%d%d",&n,&cc);
 9     for(int i=1;i<=n;++i)scanf("%d",&s[i]),m=max(m,s[i]);
10     s[0]=s[n+1]=-1;
11 }
12 void rsort()
13 {
14     for(int i=0;i<=m;++i)cs[i]=0;
15     for(int i=1;i<=n;++i)cs[rank[saf[i]]]++;
16     for(int i=1;i<=m;++i)cs[i]+=cs[i-1];
17     for(int i=n;i>=1;--i)sa[cs[rank[saf[i]]]--]=saf[i];
18 }
19 int cmp(int *f,int x,int y,int w)
20 {
21     return f[x]==f[y] && f[x+w]==f[y+w];
22 }
23 void suffix()
24 {
25     for(int i=1;i<=n;++i)rank[i]=s[i],saf[i]=i;
26     rsort();
27     for(int p=1,w=1,i;p<n;w<<=1,m=p)
28     {
29         for(i=n-w+1,p=0;i<=n;++i)saf[++p]=i;
30         for(i=1;i<=n;++i)if(sa[i]>w)saf[++p]=sa[i]-w;
31         rsort();swap(rank,saf);rank[sa[1]]=p=1;
32         for(int i=2;i<=n;++i)rank[sa[i]]=cmp(saf,sa[i],sa[i-1],w)?p:++p;
33     }
34     int j,k=0;
35     for(int i=1;i<=n;height[rank[i++]]=k)
36         for(k=k?k-1:k,j=sa[rank[i]-1];s[i+k]==s[j+k];++k);
37 }
38 bool pd(int x)
39 {
40     int num=0;
41     for(int i=1;i<=n;++i)
42     {
43         if(height[i]>=x)
44         {
45             num++;
46             if(num>=cc-1)return 1;
47         }
48         else num=0;
49     }
50     return 0;
51 }
52 int main()
53 {
54     init();
55     suffix();
56     int l=1,r=n,ans;
57     while(l<=r)
58     {
59         int mid=(l+r)>>1;
60         if(pd(mid))ans=mid,l=mid+1;
61         else r=mid-1;
62     }
63     cout<<ans;
64     return 0;
65 }
View Code

 

posted on 2018-01-15 10:28  gryzy  阅读(117)  评论(0编辑  收藏  举报

导航