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
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define maxn 40080 #define inf 0x3f3f3f3f int key[maxn],belong[maxn]; char str[maxn]; bool vis[maxn]; int sa[maxn],t[maxn],t2[maxn],c[maxn]; int height[maxn],Rank[maxn]; /* 用SA模板注意在最后添加一个比所有字符都小的字符。 key[n] = 0; build_sa(key,n+1,m); getHeight(key,n+1); 显然sa[0] 就是最后那个位置。。。 height[i] 表示 sa[i] 和 sa[i-1] 的最长公共前缀。。 */ void build_sa(int * s,int n,int m) { int i,*x = t,*y = t2; for(i = 0;i < m;i++) c[i] = 0; for(i = 0;i < n;i++) c[ x[i] = s[i] ]++; for(i = 1;i < m;i++) c[i] += c[i-1]; for(i = n-1;i >= 0;i--) sa[--c[x[i]]] = i; for(int k = 1;k <= n;k <<= 1) { int p = 0; for(i = n - k;i < n;i++) y[p++] = i; for(i = 0;i < n;i++) if(sa[i] >= k) y[p++] = sa[i] - k; for(i = 0;i < m;i++) c[i] = 0; for(i = 0;i < n;i++) c[ x[y[i]] ]++; for(i = 0;i < m;i++) c[i] += c[i-1]; for(i = n-1;i >= 0;i--) sa[--c[x[y[i]]]] = y[i]; //根据sa和y数组计算新的数y组 swap(x,y); p = 1; x[sa[0]] = 0; for(i = 1;i < n;i++) x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1] + k] == y[sa[i] + k] ? p-1:p++; if(p >= n) break; m = p; } } void getHeight(int * s,int n) { int i,j,k = 0; for(i = 0;i < n;i++) Rank[sa[i]] = i; for(i = 0;i < n;i++) { if(k) k--; int j = sa[Rank[i]-1]; while(s[i+k] == s[j+k]) k++; height[Rank[i]] = k; } } inline int min(int a,int b) { return a>b?b:a; } bool Judge(int n,int len,int num) { memset(vis,0,sizeof(vis)); vis[0] = 1;////那些用来分割的字符,他们的belong就是0 int ans = 0; if(!vis[belong[sa[1]]]) ans++; vis[belong[sa[1]]] = 1; for(int i = 2;i < n;i++) { if(height[i] >= len) { if(!vis[belong[sa[i]]]) ans++; } else { memset(vis,0,sizeof(vis)); vis[0] = 1;ans = 0; if(!vis[belong[sa[i]]]) ans++; } vis[belong[sa[i]]] = 1; if(ans >= num) return 1; } return 0; } int main() { //freopen("in.txt","r",stdin); int t; scanf("%d",&t); while(t--) { memset(belong,0,sizeof(belong)); int n; scanf("%d",&n);//n个字符串。 int pos = 0,scat = 1; int l = 0, r = inf; for(int i = 0;i < n;i++) { scanf("%s",str); int len = strlen(str); r = min(r,len); for(int j = pos;j < pos + len;j++) { key[j] = (int)str[j-pos] + 200; belong[j] = i+1; } key[pos + len] = scat++; pos += len + 1; for(int j = pos;j < pos + len;j++) { key[j] = (int)str[pos + len - j - 1] + 200; belong[j] = i+1; } key[pos + len] = scat++; pos += len + 1; } key[pos - 1] = 0; build_sa(key,pos+1,400); getHeight(key,pos+1); int ans = 0; if(n == 1) { printf("%d\n",strlen(str)); continue; } while(l <= r) { int mid = (l + r) >> 1; if(Judge(pos+1,mid,n)) { ans = mid; l = mid + 1; } else r = mid - 1; } printf("%d\n",ans); } return 0; }