后缀数组
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
1717: [Usaco2006 Dec]Milk Patterns 产奶的模式
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 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
1
2
3
2
3
2
3
1
Sample Output
4