POJ 1225 Substrings
http://poj.org/problem?id=1226
题意:给定n个串。求一个最长的串,使得这个串或者其反串在每个串中都出现过?
思路:先在大串里面加入正反串,然后二分,判定即可。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 int num[200005],ws[200005],wv[200005],wb[200005],wa[200005]; 7 int n,m,rank[200005],sa[200005],h[200005],b[200005]; 8 int read(){ 9 int t=0,f=1;char ch=getchar(); 10 while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();} 11 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 12 return t*f; 13 } 14 bool cmp(int *r,int a,int b,int l){ 15 return r[a]==r[b]&&r[a+l]==r[b+l]; 16 } 17 void da(int *r,int *sa,int n,int m){ 18 int *y=wb,*x=wa,*t,i,j,p; 19 for (i=0;i<m;i++) ws[i]=0; 20 for (i=0;i<n;i++) x[i]=r[i]; 21 for (i=0;i<n;i++) ws[x[i]]++; 22 for (i=1;i<m;i++) ws[i]+=ws[i-1]; 23 for (i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; 24 for (p=1,j=1;p<n;m=p,j*=2){ 25 for (p=0,i=n-j;i<n;i++) y[p++]=i; 26 for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j; 27 for (i=0;i<m;i++) ws[i]=0; 28 for (i=0;i<n;i++) wv[i]=x[y[i]]; 29 for (i=0;i<n;i++) ws[wv[i]]++; 30 for (i=1;i<m;i++) ws[i]+=ws[i-1]; 31 for (i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; 32 for (t=x,x=y,y=t,i=1,p=1,x[sa[0]]=0;i<n;i++) 33 x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++; 34 } 35 } 36 void cal(int *r,int n){ 37 int i,j,k=0; 38 for (i=1;i<=n;i++) rank[sa[i]]=i; 39 for (i=0;i<n;h[rank[i++]]=k) 40 for (k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); 41 } 42 bool check(int x){ 43 int L,R; 44 int hash[105]; 45 for (int i=1;i<=n;i++){ 46 L=i; 47 while (L<=n&&h[L]<x) L++; 48 if (L>n) break; 49 R=L; 50 while (R<=n&&h[R]>=x) R++; 51 memset(hash,0,sizeof hash); 52 for (int j=L-1;j<=R-1;j++) 53 if (b[sa[j]]<=m) 54 hash[b[sa[j]]]=1; 55 int j=0; 56 for (j=1;j<=m;j++) 57 if (!hash[j]) break; 58 if (j>m) return 1; 59 i=R; 60 } 61 return 0; 62 } 63 void solve(){ 64 int l=0,r=100,ans; 65 while (l<=r){ 66 int mid=(l+r)>>1; 67 if (check(mid)) ans=mid,l=mid+1; 68 else r=mid-1; 69 } 70 printf("%d\n",ans); 71 } 72 int main(){ 73 int T=read(); 74 char s[200005]; 75 while (T--){ 76 m=read();n=0;int sx=130; 77 for (int i=1;i<=m;i++){ 78 scanf("%s",s); 79 int len=strlen(s); 80 for (int j=0;j<len;j++) 81 num[n]=s[j],b[n++]=i; 82 num[n]=sx++;b[n++]=n+1; 83 for (int j=len-1;j>=0;j--) 84 num[n]=s[j],b[n++]=i; 85 num[n]=sx++;b[n++]=n+1; 86 } 87 num[n]=0;b[n]=n+1; 88 da(num,sa,n+1,sx+10); 89 cal(num,n); 90 solve(); 91 } 92 }