【bzoj1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 SA+二分

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

题解

  求出相邻lcp后,二分长度,判断相邻的是不是连续超过k个即可。

  为什么这样是对的。

  因为两串相同的最长超过k的长度,那么绝对是相邻lcp超过k次对吧,脑补。

 1 #include<cstring>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<iostream>
 6 
 7 #define N 20007
 8 using namespace std;
 9 inline int read()
10 {
11     int x=0,f=1;char ch=getchar();
12     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
13     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 
17 int n,k;
18 int s[N],sa[N],rk[N*2],A[N];
19 int a[N],b[N],cnta[N],cntb[N],tsa[N],height[N];
20 
21 void Get_SA()
22 {
23     for (int i=1;i<=n;i++)cnta[i]=0;
24     for (int i=1;i<=n;i++)cnta[s[i]]++;
25     for (int i=1;i<=n;i++)cnta[i]+=cnta[i-1];
26     for (int i=n;i>=1;i--)sa[cnta[s[i]]--]=i;
27     rk[sa[1]]=1;
28     for (int i=2;i<=n;i++)rk[sa[i]]=rk[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]);
29     for (int i=1;rk[sa[n]]!=n;i<<=1)
30     {
31         for (int j=1;j<=n;j++)a[j]=rk[j],b[j]=rk[j+i];
32         for (int j=0;j<=n;j++)cnta[j]=cntb[j]=0;
33         for (int j=1;j<=n;j++)cnta[a[j]]++,cntb[b[j]]++;
34         for (int j=1;j<=n;j++)cnta[j]+=cnta[j-1],cntb[j]+=cntb[j-1];
35         for (int j=n;j>=1;j--)tsa[cntb[b[j]]--]=j;
36         for (int j=n;j>=1;j--)sa[cnta[a[tsa[j]]]--]=tsa[j];
37         rk[sa[1]]=1;
38         for (int j=2;j<=n;j++)
39             rk[sa[j]]=rk[sa[j-1]]+(a[sa[j]]!=a[sa[j-1]]||b[sa[j]]!=b[sa[j-1]]);
40     }
41 }
42 void Get_Height()
43 {
44     int len=0;
45     for (int i=1;i<=n;i++)
46     {
47         if (len) len--;
48         while(s[i+len]==s[sa[rk[i]-1]+len])len++;
49         height[rk[i]]=len;
50     }
51 }
52 bool check(int x)
53 {
54     int tot=0;
55     for (int i=2;i<=n;i++)
56     {
57         if (height[i]>=x)tot++;else tot=0;
58         if (tot>=k-1)return 1;
59     }
60     return 0;
61 }
62 int mid_find(int l,int r)
63 {
64     while(l<r)
65     {
66         int mid=(l+r+1)>>1;
67         if (check(mid))l=mid;
68         else r=mid-1;
69     }
70     return l;
71 }
72 int main()
73 {
74     n=read(),k=read();
75     for (int i=1;i<=n;i++) A[i]=s[i]=read();
76     sort(A+1,A+n+1);
77     int cnt=n;cnt=unique(A+1,A+cnt+1)-A-1;
78     for (int i=1;i<=n;i++)
79         s[i]=lower_bound(A+1,A+cnt+1,s[i])-A;
80     Get_SA();
81     Get_Height();
82     /*for (int i=1;i<=n;i++)cout<<height[i]<<" ";
83     cout<<endl;*/
84     printf("%d\n",mid_find(0,n));
85 }

 

posted @ 2018-01-12 18:49  Kaiser-  阅读(208)  评论(0编辑  收藏  举报