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
2 3 ABCD BCDFF BRCD 2 rose orchid
Sample Output
2 2
题意:给定一些字符串,求出现或者翻转后出现在每一个串中的最长子串。
解题思路:将每一个串以及翻转后的串都连起来,中间用不相同且未出现过的字符分割开,然后二分长度,根据后缀数组height值分组判定。
代码:
/* *********************************************** Author :xianxingwuguan Created Time :2014-2-1 2:59:27 File 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; }