poj 1226 Substrings
Description
You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings.
Input
The first line of the input contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains a single integer n (1 <= n <= 100), the number of given strings, followed by n lines, each representing one string of minimum length 1 and maximum length 100. There is no extra white space before and after a string.
Output
There should be one line per test case containing the length of the largest string found.
Sample Input
2 3 ABCD BCDFF BRCD 2 rose orchid
Sample Output
2 2
思路: 本题和poj2774很像,2774是只有两个串,而这里是有n个串,这题也可以暴力kmp去做。当然了,用后缀数组来做这题更好,由于h数组的特殊性质,这题我们可以把每个字符串正向
和反向连在一起,每个字符串中间都间隔一个特殊的不同的字符。 然后求出sa数组和h数组以后,我们就二分枚举答案,从h[1],h[2]不断枚举下去,看是否比mid大,如果大于等于mid,
我们就看他们所在的原位置是否属于原来的那n个字符串,如果筹齐了n个字符串,则说明mid可行。
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 int const N=20000+1000; 8 int n,t[N],num[N],wa[N<<1],wb[N<<1],wv[N],sa[N],rk[N],h[N]; 9 int s[N]; 10 char s1[103]; 11 int cmp(int *r,int x,int y,int z){ 12 return r[x]==r[y] && r[x+z]==r[y+z]; 13 } 14 void build_sa(int *r,int *sa,int n,int m){ 15 int i,j,p,*x=wa,*y=wb; 16 for(i=0;i<m;i++) num[i]=0; 17 for(i=0;i<n;i++) num[x[i]=r[i]]++; 18 for(i=1;i<m;i++) num[i]+=num[i-1]; 19 for(i=n-1;i>=0;i--) sa[--num[x[i]]]=i; 20 for(p=1,j=1;p<n;j<<=1,m=p){ 21 for(p=0,i=n-j;i<n;i++) y[p++]=i; 22 for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; 23 for(i=0;i<m;i++) num[i]=0; 24 for(i=0;i<n;i++) wv[i]=x[y[i]]; 25 for(i=0;i<n;i++) num[wv[i]]++; 26 for(i=1;i<m;i++) num[i]+=num[i-1]; 27 for(i=n-1;i>=0;i--) sa[--num[wv[i]]]=y[i]; 28 swap(x,y); 29 for(p=1,x[sa[0]]=0,i=1;i<n;i++) 30 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++; 31 } 32 for(i=0;i<n;i++) rk[i]=x[i]; 33 } 34 void build_h(int *r,int *sa,int n){ 35 int k=0; 36 for(int i=0;i<n;i++){ 37 if(k) k--; 38 int j=sa[rk[i]-1]; 39 while ( r[i+k]==r[j+k]) k++; 40 h[rk[i]]=k; 41 } 42 } 43 int check(int mid,int m){ 44 int vis[101],num=0; 45 memset(vis,0,sizeof(vis)); 46 for(int i=1;i<=m;i++){ 47 if(h[i]>=mid){ 48 if(!vis[t[sa[i]]]){ 49 num++;vis[t[sa[i]]]=1; 50 } 51 if(!vis[t[sa[i-1]]]){ 52 num++; vis[t[sa[i-1]]]=1; 53 } 54 if(num==n) return 1; 55 }else { 56 num=0; 57 memset(vis,0,sizeof(vis)); 58 } 59 } 60 return 0; 61 } 62 int main(){ 63 int cas; 64 scanf("%d",&cas); 65 while (cas--){ 66 scanf("%d",&n); 67 int m=0,tot=130; 68 for(int i=0;i<n;i++){ 69 scanf("%s",s1); 70 int len=strlen(s1); 71 for(int j=0;j<len;j++) s[m++]=s1[j],t[m-1]=i+1; 72 s[m++]=tot++; 73 for(int j=len-1;j>=0;j--) s[m++]=s1[j],t[m-1]=i+1; 74 s[m++]=tot++; 75 } 76 s[m]=0; 77 build_sa(s,sa,m+1,330); 78 build_h(s,sa,m); 79 int l=0,r=100,ans=0; 80 while (l<=r){ 81 int mid=(l+r)/2; 82 if(check(mid,m)){ 83 ans=mid; l=mid+1; 84 }else r=mid-1; 85 } 86 printf("%d\n",ans); 87 } 88 return 0; 89 }