BZOJ 1717 [Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组)
【题目链接】http://www.lydsy.com/JudgeOnline/problem.php?id=1717
【题目大意】
求一个最长的串,使得其在母串中出现的次数达到要求
【题解】
二分答案,利用后缀数组求出的height数组进行检验
【代码】
#include <cstdio> #include <cstring> using namespace std; const int N=2000010; int n,k,rank[N],sa[N],h[N],tmp[N],cnt[N],s[N]; void suffixarray(int n,int m){ int i,j,k;n++; for(i=0;i<2*n+5;i++)rank[i]=sa[i]=h[i]=tmp[i]=0; for(i=0;i<m;i++)cnt[i]=0; for(i=0;i<n;i++)cnt[rank[i]=s[i]]++; for(i=1;i<m;i++)cnt[i]+=cnt[i-1]; for(i=0;i<n;i++)sa[--cnt[rank[i]]]=i; for(k=1;k<=n;k<<=1){ for(i=0;i<n;i++){ j=sa[i]-k; if(j<0)j+=n; tmp[cnt[rank[j]]++]=j; }sa[tmp[cnt[0]=0]]=j=0; for(i=1;i<n;i++){ if(rank[tmp[i]]!=rank[tmp[i-1]]||rank[tmp[i]+k]!=rank[tmp[i-1]+k])cnt[++j]=i; sa[tmp[i]]=j; }memcpy(rank,sa,n*sizeof(int)); memcpy(sa,tmp,n*sizeof(int)); if(j>=n-1)break; }for(j=rank[h[i=k=0]=0];i<n-1;i++,k++) while(~k&&s[i]!=s[sa[j-1]+k])h[j]=k--,j=rank[sa[j]+1]; } int main(){ scanf("%d%d",&n,&k); for(int i=0;i<n;i++)scanf("%d",s+i); suffixarray(n,1000010); int l=1,r=n; while(l<=r){ int mid=(l+r)>>1,tot=1; for(int i=1;i<=n;i++){ if(h[i]>=mid){ if(++tot>=k){l=mid+1;break;} }else tot=1; }if(tot<k)r=mid-1; }return printf("%d\n",r),0; }
愿你出走半生,归来仍是少年