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
题意:求出所有串中,最长的子串长度(子串不一定要相等,子串反转后相等也行)
思路:二分子串长度,将每个串和其反串合并成一个数组,然后求后缀数组,并记录每个串长度前缀和(长度前缀和指的是加上该串和其反串后整个字符长)
然后对于ht数组,如果当前ht数组所对应的sa【i】和sa【i-1】出现的串之前没出现过,那么种类数+1,直到种类数 == n
如果中途发现ht < mid 那么就清空之前所记录的信息,重新匹配
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 8 int T,n; 9 const int maxn = 2e5+5; 10 string s; 11 int sa[maxn],t[maxn],t2[maxn],c[maxn],len[105]; 12 13 void build_sa(int n,int m) 14 { 15 int i,*x=t,*y=t2; 16 for(i=0; i<m; i++)c[i]=0; 17 for(i=0; i<n; i++)c[x[i]=s[i]]++; 18 for(i=1; i<m; i++)c[i]+=c[i-1]; 19 for(i=n-1; i>=0; i--)sa[--c[x[i]]]=i; 20 for(int k=1; k<=n; k<<=1) 21 { 22 int p=0; 23 for(i=n-k; i<n; i++)y[p++]=i; 24 for(i=0; i<n; i++)if(sa[i] >= k)y[p++]=sa[i]-k; 25 for(i=0; i<m; i++)c[i] = 0; 26 for(i=0; i<n; i++)c[x[y[i]]]++; 27 for(i=1; i<m; i++)c[i]+=c[i-1]; 28 for(i=n-1; i>=0; i--)sa[--c[x[y[i]]]] = y[i]; 29 swap(x,y); 30 p=1,x[sa[0]]=0; 31 for(i=1; i<n; i++) 32 x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k]?p-1:p++; 33 if(p>=n)break; 34 m=p; 35 } 36 } 37 38 int ht[maxn],rk[maxn]; 39 40 void getHeight(int n) 41 { 42 int i,j,k=0; 43 for(i=0; i<n; i++)rk[sa[i]] = i; 44 for(i=0; i<n-1; i++) 45 { 46 if(k)k--; 47 if(s[i] == '$')continue; 48 int j = sa[rk[i]-1]; 49 while(s[i+k] == s[j+k] && s[i+k] != '$')k++; 50 ht[rk[i]] = k; 51 } 52 } 53 54 bool vis[105]; 55 bool check(int mid) 56 { 57 memset(vis,0,sizeof(vis)); 58 int cnt=0; 59 bool flag = 0; 60 for(int i=1; i<len[n]; i++) 61 { 62 if(ht[i] >= mid && s[sa[i]] != '$') 63 { 64 65 for(int j=1; j<=n; j++) 66 { 67 if(!flag) 68 { 69 //printf("%d $$$$ %d %d\n",sa[i-1]+1,len[j-1],len[j]); 70 if(sa[i-1]+1 > len[j-1] && sa[i-1]+1 < len[j])if(!vis[j])vis[j]=1,cnt++,flag = 1; 71 } 72 if(sa[i]+1 > len[j-1] && sa[i]+1 < len[j])if(!vis[j])vis[j] = 1,cnt++; 73 } 74 // printf("============================================\n",flag); 75 } 76 else 77 { 78 if(cnt == n)return 1; 79 cnt = 0; 80 flag = 0; 81 memset(vis,0,sizeof(vis)); 82 } 83 } 84 if(cnt == n)return 1; 85 return 0; 86 } 87 char tmp[200]; 88 int main() 89 { 90 scanf("%d",&T); 91 while(T--) 92 { 93 scanf("%d",&n); 94 s.clear(); 95 for(int i=1; i<=n; i++) 96 { 97 scanf("%s",tmp); 98 int tmp_len = strlen(tmp); 99 s+=tmp; 100 s+='$'; 101 reverse(tmp,tmp+tmp_len); 102 s+=tmp; 103 s+='$'; 104 len[i] = s.length(); 105 } 106 // for(int i=1;i<=n;i++)printf("%d =========\n",len[i]); 107 // if(n == 1) 108 // { 109 // printf("%d\n",len[1]/2-1); 110 // continue; 111 // } 112 build_sa(len[n],130); 113 getHeight(len[n]); 114 int L = 1,R = len[n]; 115 int pos = 0; 116 while(L <= R) 117 { 118 int mid = (L+R)/2; 119 if(check(mid))pos = mid,L=mid+1; 120 else R = mid-1; 121 } 122 cout << pos << endl; 123 } 124 125 }