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 }

 









posted @ 2019-06-01 12:00  zjxxcn  阅读(113)  评论(0编辑  收藏  举报