http://www.spoj.com/problems/PHRASES/
题意:给n个串,求n个串里面都有2个不重叠的最长的字串长度。
思路:二分答案,然后就可以嘿嘿嘿
PS:辣鸡题目毁我青春,一开始二分的时候ans没有赋初值为0,结果没答案的时候就会输出奇怪的数字T_T,其实主要还是怪我不小心。。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 int len,num[500005],ws[500005],wv[500005],wa[500005],wb[500005],h[500005],sa[500005],rank[500005]; 7 int f[500005][2],N,b[500005]; 8 char s[500005]; 9 int read(){ 10 int t=0,f=1;char ch=getchar(); 11 while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();} 12 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 13 return t*f; 14 } 15 bool cmp(int *r,int a,int b,int l){ 16 return r[a]==r[b]&&r[a+l]==r[b+l]; 17 } 18 void da(int *r,int *sa,int n,int m){ 19 int *t,*x=wa,*y=wb,i,j,k,p; 20 for (i=0;i<m;i++) ws[i]=0; 21 for (i=0;i<n;i++) x[i]=r[i]; 22 for (i=0;i<n;i++) ws[x[i]]++; 23 for (i=1;i<m;i++) ws[i]+=ws[i-1]; 24 for (i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; 25 for (j=1,p=1;p<n;j*=2,m=p){ 26 for (p=0,i=n-j;i<n;i++) y[p++]=i; 27 for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j; 28 for (i=0;i<m;i++) ws[i]=0; 29 for (i=0;i<n;i++) wv[i]=x[y[i]]; 30 for (i=0;i<n;i++) ws[wv[i]]++; 31 for (i=1;i<m;i++) ws[i]+=ws[i-1]; 32 for (i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; 33 for (t=x,x=y,y=t,i=1,x[sa[0]]=0,p=1;i<n;i++){ 34 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 35 } 36 } 37 } 38 void cal(int *r,int n){ 39 int i,j,k=0; 40 for (int i=1;i<=n;i++) rank[sa[i]]=i; 41 for (int i=0;i<n;h[rank[i++]]=k){ 42 for (k?k--:0,j=sa[rank[i]-1];r[j+k]==r[i+k];k++); 43 } 44 } 45 bool check(int mid){ 46 int l,r; 47 for (int i=1;i<=len;i++){ 48 l=i; 49 while (l<=len&&h[l]<mid) l++; 50 r=l; 51 while (r<=len&&h[r]>=mid) r++; 52 for (int j=1;j<=N;j++) f[j][0]=0x3f3f3f3f,f[j][1]=-0x3f3f3f3f; 53 for (int j=l-1;j<=r-1;j++){ 54 int k=b[sa[j]]; 55 if (k==N+1) continue; 56 f[k][0]=std::min(f[k][0],sa[j]); 57 f[k][1]=std::max(f[k][1],sa[j]); 58 } 59 int j=0; 60 for (j=1;j<=N;j++){ 61 if (f[j][0]==0x3f3f3f3f) break; 62 if (f[j][1]-f[j][0]<mid) break; 63 } 64 if (j>N) return 1; 65 i=r; 66 } 67 return 0; 68 } 69 void solve(){ 70 int l=1,r=20000,ans=0; 71 while (l<=r){ 72 int mid=(l+r)>>1; 73 if (check(mid)) ans=mid,l=mid+1; 74 else r=mid-1; 75 } 76 printf("%d ",ans); 77 } 78 int main(){ 79 int T=read(); 80 while (T--){ 81 len=0; 82 int n=read(); 83 for (int i=1;i<=n;i++){ 84 scanf("%s",s+1); 85 int Len=strlen(s+1); 86 for (int j=1;j<=Len;j++) 87 num[len]=s[j],b[len++]=i; 88 if (i<n) num[len]=290+i,b[len++]=n+1; 89 } 90 num[len]=0;b[len]=n+1; 91 da(num,sa,len+1,310); 92 cal(num,len); 93 N=n; 94 solve(); 95 } 96 }