[Poj3261] [Bzoj1717] [后缀数组论文例题,USACO 2006 December Gold] Milk Patterns [后缀数组可重叠的k次最长重复子串]
和上一题(POJ1743,上一篇博客)相似,只是二分的判断条件是:是否存在一段后缀的个数不小于k
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 #include <map> 9 10 using namespace std; 11 12 int t; 13 int str[21000],A[21000],B[21000],U[21000],Tmp[21000],SA[21000],H[21000]; 14 map <int,int> Map; 15 16 void Calc_H(const int n,const int * Rank) 17 { 18 int i,j,k=0; 19 for(i=0;i<n;H[Rank[i++]]=k) 20 for(k?k--:0,j=SA[Rank[i]-1];str[i+k]==str[j+k];++k); 21 return ; 22 } 23 24 bool cmp(const int * s,const int a,const int b,const int l) 25 { 26 return s[a]==s[b] && s[a+l]==s[b+l]; 27 } 28 29 int* Get_SA(const int n,int m) 30 { 31 int i,j,p,*x=A,*y=B; 32 33 for(i=0;i<n;++i)U[i]=0; 34 for(i=0;i<n;++i)U[x[i]=str[i]]++; 35 for(i=1;i<m;++i)U[i]+=U[i-1]; 36 for(i=n-1;i>=0;--i)SA[--U[x[i]]]=i; 37 38 for(j=1,p=1;p<n;j<<=1,m=p) 39 { 40 for(p=0,i=n-j;i<n;++i)y[p++]=i; 41 for(i=0;i<n;++i)if(SA[i]>=j)y[p++]=SA[i]-j; 42 for(i=0;i<n;++i)Tmp[i]=x[y[i]]; 43 for(i=0;i<m;++i)U[i]=0; 44 for(i=0;i<n;++i)U[Tmp[i]]++; 45 for(i=1;i<m;++i)U[i]+=U[i-1]; 46 for(i=n-1;i>=0;--i)SA[--U[Tmp[i]]]=y[i]; 47 for(swap(x,y),p=1,x[SA[0]]=0,i=1;i<n;++i) 48 x[SA[i]]=cmp(y,SA[i-1],SA[i],j)?p-1:p++; 49 } 50 51 Calc_H(n,x); 52 return x; 53 } 54 55 bool Check(const int lim,const int n) 56 { 57 int cnt=0; 58 for(int i=1;i<=n;++i) 59 { 60 if(i>1 && H[i]<lim) 61 { 62 if(cnt>=t)return true; 63 cnt=1; 64 } 65 if(H[i]>=lim)cnt++; 66 } 67 if(cnt>=t)return true; 68 return false; 69 } 70 71 int main() 72 { 73 int i,l,r,n,cnt=0; 74 75 scanf("%d%d",&n,&t); 76 for(i=0;i<n;++i) 77 { 78 scanf("%d",&str[i]); 79 if(!Map[str[i]])Map[str[i]]=++cnt; 80 str[i]=Map[str[i]]; 81 } 82 83 Get_SA(n+1,21000); 84 85 l=0;r=n; 86 while(l<r-1) 87 { 88 int mid=l+((r-l)>>1); 89 if(Check(mid,n))l=mid; 90 else r=mid; 91 } 92 93 printf("%d\n",l); 94 95 return 0; 96 }