Substrings
Time Limit: 1000MS |
|
Memory Limit: 10000K |
Total Submissions: 10998 |
|
Accepted: 3824 |
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
23ABCDBCDFFBRCD2roseorchid
Sample Output
22
題意:給定一些字串,求出現或者翻轉後出現在每一個串中的最長子串。
解題思路:將每一個串以及翻轉後的串都連起來,中間用不相同且未出現過的字元分割開,然後二分長度,根據尾碼數組height值分組判定。
代碼:
/* ***********************************************Author :xianxingwuguanCreated Time :2014-2-1 2:59:27File Name :1.cpp************************************************ */#pragma comment(linker, "/STACK:102400000,102400000")#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;const int maxn=30100;const double pi =acos(-1.0);const double eps =1e-8;int height[maxn],sa[maxn],rank[maxn],c[maxn],t1[maxn],t2[maxn]; void da(int *str,int n,int m) { int i,j,k,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=str[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(k=1;k<=n;k<<=1) { 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=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++; if(p>=n)break; m=p; } } void calheight(int *str,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--; j=sa[rank[i]-1]; while(str[i+k]==str[j+k])k++; height[rank[i]]=k; } // printf("sa:");for(i=0;i<=n;i++)printf("%d ",sa[i]);puts(""); // printf("rank:");for(i=0;i<=n;i++)printf("%d ",rank[i]);puts(""); // printf("height:");for(i=0;i<=n;i++)printf("%d ",height[i]);puts(""); } int str[maxn],loc[maxn],vis[maxn];char ss[maxn];int n;bool check(int mid,int len){ int i,j,tot; tot=0; memset(vis,0,sizeof(vis)); for(i=2;i<=len;i++) { if(height[i]<mid) { memset(vis,0,sizeof(vis)); tot=0; } else { if(!vis[loc[sa[i-1]]]) { vis[loc[sa[i-1]]]=1; tot++; } if(!vis[loc[sa[i]]]){ vis[loc[sa[i]]]=1; tot++; } if(tot==n)return 1; } } return 0; } int main(){ //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int T,i,j; scanf("%d",&T); while(T--) { scanf("%d",&n); int len=0; int ff=200; int left=0,right; for(i=1;i<=n;i++) { scanf("%s",ss); int cnt=strlen(ss); right=cnt; for(j=0;j<cnt;j++)str[len]=ss[j]+500,loc[len++]=i; str[len]=ff; loc[len++]=ff++; for(j=cnt-1;j>=0;j--)str[len]=ss[j]+500,loc[len++]=i; str[len]=ff; loc[len++]=ff++; } str[len]=0; // cout<<"len="<<len<<endl; da(str,len+1,1000); calheight(str,len); while(left<right) { int mid=(left+right+1)>>1; if(check(mid,len))left=mid; else right=mid-1; } printf("%d\n",left); } return 0;}