后缀数组
o(︶︿︶)o 唉傻逼了一下,忘了把后缀数组的字典范围改回20001,直接21交了上去,白白RE了两发……sigh
既然要找出现了K次的子串嘛,那当然要用后缀数组了>_>(因为我太弱不会自动机&树)
ok离散化后上后缀数组,求出height数组>_>然后用个……ST表= =?!
O(n)地扫一遍所有的区间……看所有长度为k的里面最大的min(i,i+k-1)是多少(当然,k要减一,因为是K个子串的话对应的是K-1个串的LCP)
水题还RE了两发→_→真是难过
/**************************************************************
Problem: 1717
User: Tunix
Language: C++
Result: Accepted
Time:40 ms
Memory:12224 kb
****************************************************************/ //BZOJ 1717
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
typedef long long LL;
inline int getint(){
int r=,v=; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-;
for(; isdigit(ch);ch=getchar()) v=v*+ch-'';
return r*v;
}
const int N=1e5+,INF=~0u>>;
/****************template***********************/
int a[N],b[N];
int n,k,SA[N],rank[N],height[N],wa[N],wb[N],c[N];
bool cmp(int *r,int a,int b,int l){
return r[a]==r[b] && r[a+l]==r[b+l];
}
void DA(int *s,int *sa,int n,int m){
int i,j,p,*x=wa,*y=wb;
rep(i,m) c[i]=;
rep(i,n) c[x[i]=s[i]]++;
F(i,,m-) c[i]+=c[i-];
D(i,n-,) sa[--c[x[i]]]=i;
for(j=,p=;p<n;j<<=,m=p){
for(p=,i=n-j;i<n;i++) y[p++]=i;
rep(i,n) if (sa[i]>=j) y[p++]=sa[i]-j; rep(i,m) c[i]=;
rep(i,n) c[x[y[i]]]++;
F(i,,m-) c[i]+=c[i-];
D(i,n-,) sa[--c[x[y[i]]]]=y[i];
swap(x,y); p=; x[sa[]]=;
F(i,,n-) x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
}
void calheight(int *s,int *sa,int n){
int k=;
F(i,,n) rank[sa[i]]=i;
rep(i,n){
if (k) k--;
int j=sa[rank[i]-];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
int f[N][];
void ST(){
F(i,,n) f[i][]=height[i];
for(int j=;(<<j)<=n;j++)
for(int i=;i+(<<j)-<=n;i++)
f[i][j]=min(f[i][j-],f[i+(<<(j-))][j-]);
}
int query(int l,int r){
int k=log(r-l+)/log();
return min(f[l][k],f[r-(<<k)+][k]);
}
int main(){
n=getint(); k=getint()-;
rep(i,n) a[i]=b[i]=getint();
sort(b,b+n);
int num=unique(b,b+n)-b;
rep(i,n) a[i]=lower_bound(b,b+num,a[i])-b+;
a[n]=;
DA(a,SA,n+,);
calheight(a,SA,n);
ST();
int ans=;
F(i,,n-k+) ans=max(query(i,i+k-),ans);
printf("%d\n",ans);
return ;
}
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
1
2
3
2
3
2
3
1
Sample Output
4