后缀数组+二分答案+离散化。(上次写的时候看数据小没离散化然后一直WA。。。写了lsj师兄的写法。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define REP(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=20005; const int inf=0x7f7f7f7f; struct node{ int id[nmax],N; node(){ N=0; } inline void add(int x){ id[N++]=x; } inline void work(){ sort(id,id+N); N=unique(id,id+N)-id; } inline int hash(int x){ return lower_bound(id,id+N,x)-id; } }h; int sa[nmax],t[nmax],t2[nmax],c[nmax],rank[nmax],height[nmax],S[nmax],N,K; void build_sa(){ int m=h.N,*x=t,*y=t2; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<N;i++) c[x[i]=S[i]]++; for(int i=1;i<m;i++) c[i]+=c[i-1]; for(int i=N-1;i>=0;i--) sa[--c[x[i]]]=i; for(int k=1;k<=N;k<<=1){ int p=0; for(int i=N-k;i<N;i++) y[p++]=i; for(int i=0;i<N;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<N;i++) c[x[i]]++; for(int i=1;i<m;i++) c[i]+=c[i-1]; for(int i=N-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y);p=1;x[sa[0]]=0; for(int i=1;i<N;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=N) break; m=p; } } void build_height(){ int k=0; for(int i=0;i<N;i++) rank[sa[i]]=i; for(int i=0;i<N;i++){ if(k) k--; int j=sa[rank[i]-1]; while(S[i+k]==S[j+k]) k++; height[rank[i]]=k; } } bool check(int x){ int cnt=1; for(int i=1;i<N;i++){ if(height[i]>=x){ cnt++; if(cnt>=K) return true; }else cnt=1; } return false; } int main(){ N=read(),K=read(); REP(i,0,N-1) S[i]=read(),h.add(S[i]); h.add(S[N++]=-inf);h.work(); REP(i,0,N-1) S[i]=h.hash(S[i]); build_sa();build_height(); int l=0,r=N,ans=0,mid; while(l<=r){ mid=(l+r)>>1; if(check(mid)) ans=mid,l=mid+1; else r=mid-1; } printf("%d ",ans); return 0; }
1717: [Usaco2006 Dec]Milk Patterns 产奶的模式
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 948 Solved: 516
[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