【BZOJ】【1717】【USACO 2006 Dec】Milk Patterns产奶的模式

后缀数组


  o(︶︿︶)o 唉傻逼了一下,忘了把后缀数组的字典范围改回20001,直接21交了上去,白白RE了两发……sigh

  既然要找出现了K次的子串嘛,那当然要用后缀数组了>_>(因为我太弱不会自动机&树)

  ok离散化后上后缀数组,求出height数组>_>然后用个……ST表= =?!

  O(n)地扫一遍所有的区间……看所有长度为k的里面最大的min(i,i+k-1)是多少(当然,k要减一,因为是K个子串的话对应的是K-1个串的LCP)

  水题还RE了两发→_→真是难过

 1 /**************************************************************
 2     Problem: 1717
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:40 ms
 7     Memory:12224 kb
 8 ****************************************************************/
 9  
10 //BZOJ 1717
11 #include<cmath>
12 #include<vector>
13 #include<cstdio>
14 #include<cstring>
15 #include<cstdlib>
16 #include<iostream>
17 #include<algorithm>
18 #define rep(i,n) for(int i=0;i<n;++i)
19 #define F(i,j,n) for(int i=j;i<=n;++i)
20 #define D(i,j,n) for(int i=j;i>=n;--i)
21 #define pb push_back
22 using namespace std;
23 typedef long long LL;
24 inline int getint(){
25     int r=1,v=0; char ch=getchar();
26     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
27     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
28     return r*v;
29 }
30 const int N=1e5+10,INF=~0u>>2;
31 /****************template***********************/
32 int a[N],b[N];
33 int n,k,SA[N],rank[N],height[N],wa[N],wb[N],c[N];
34 bool cmp(int *r,int a,int b,int l){
35     return r[a]==r[b] && r[a+l]==r[b+l];
36 }
37 void DA(int *s,int *sa,int n,int m){
38     int i,j,p,*x=wa,*y=wb;
39     rep(i,m) c[i]=0;
40     rep(i,n) c[x[i]=s[i]]++;
41     F(i,1,m-1) c[i]+=c[i-1];
42     D(i,n-1,0) sa[--c[x[i]]]=i;
43     for(j=1,p=0;p<n;j<<=1,m=p){
44         for(p=0,i=n-j;i<n;i++) y[p++]=i;
45         rep(i,n) if (sa[i]>=j) y[p++]=sa[i]-j;
46  
47         rep(i,m) c[i]=0;
48         rep(i,n) c[x[y[i]]]++;
49         F(i,1,m-1) c[i]+=c[i-1];
50         D(i,n-1,0) sa[--c[x[y[i]]]]=y[i];
51         swap(x,y); p=1; x[sa[0]]=0;
52         F(i,1,n-1) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
53     }
54 }
55 void calheight(int *s,int *sa,int n){
56     int k=0;
57     F(i,1,n) rank[sa[i]]=i;
58     rep(i,n){
59         if (k) k--;
60         int j=sa[rank[i]-1];
61         while(s[i+k]==s[j+k]) k++;
62         height[rank[i]]=k;
63     }
64 }
65 int f[N][20];
66 void ST(){
67     F(i,1,n) f[i][0]=height[i];
68     for(int j=1;(1<<j)<=n;j++)
69         for(int i=1;i+(1<<j)-1<=n;i++)
70             f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
71 }
72 int query(int l,int r){
73     int k=log(r-l+1)/log(2);
74     return min(f[l][k],f[r-(1<<k)+1][k]);
75 }
76 int main(){
77     n=getint(); k=getint()-1;
78     rep(i,n) a[i]=b[i]=getint();
79     sort(b,b+n);
80     int num=unique(b,b+n)-b;
81     rep(i,n) a[i]=lower_bound(b,b+num,a[i])-b+2;
82     a[n]=0;
83     DA(a,SA,n+1,20001);
84     calheight(a,SA,n);
85     ST();
86     int ans=0;
87     F(i,1,n-k+1) ans=max(query(i,i+k-1),ans);
88     printf("%d
",ans);
89     return 0;
90 }
91 
View Code

1717: [Usaco2006 Dec]Milk Patterns 产奶的模式

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 588  Solved: 331
[Submit][Status][Discuss]

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

HINT

Source

[Submit][Status][Discuss]
原文地址:https://www.cnblogs.com/Tunix/p/4399204.html