。。。。数据太小,就直接用暴力n^3的做法了
以第一个串为主,枚举它的所有子串,看某个子串是否为其余所有字符串的 子串,如果是,则为公共子串
然后合法的子串里面找一个最长的,字典序最小的。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const int mod=1000000007;
int min(int a,int b)
{return a<b?a:b;}
int max(int a,int b)
{return a>b?a:b;}
char tm[15][100];
char first[100];
char ans2[100][100];
int cmp(char *s1,char* s2)
{
return strcmp(s1,s2)<0;
}
int val[100];
void getnext(char *s,int len)
{
int i=1,j=0;
val[1]=0;
while(i<len)
{
if (j==0||s[i]==s[j])
{i++;j++;val[i]=j;}
else
j=val[j];
}
}
int kmp(char *s1,char *s2,int len1)//s1-子串,s2-字典
{
int len2=strlen(s2+1);
int i=1,j=1;
while(i<=len1&&j<=len2)
{
if (i==0||s1[i]==s2[j])
{i++,j++;}
else
i=val[i];
}
if (i>len1)
return i-len1;
else
return -1;
}
struct node
{
int i,j;
node(){}
node(int a,int b)
{i=a;j=b;}
};
node ans[60*60*2];
int main()
{
int t;cin>>t;
while(t--)
{
int maxlen=0;
int maxnum=0;
int m;
int i,j;
cin>>m;
scanf("%s",first+1);
int len1=strlen(first+1);
for (i=1;i<=m-1;i++)
{
scanf("%s",tm[i]+1);
}
for (i=1;i<=len1;i++)
{
for (j=i;j<=len1;j++)
{
if (j-i+1<maxlen) continue;
char sub[100];
int k;
for (k=i;k<=j;k++)
sub[k-i+1]=first[k];
sub[j-i+2]=0;
getnext(sub,j-i+1);
int ret;
int flag=0;
for (int h=1;h<=m-1;h++)
{
ret=kmp(sub,tm[h],j-i+1);
if (ret==-1)
{flag=1;break;}
}
if (!flag)
{
ans[++maxnum]=node(i,j);
if (j-i+1>maxlen) maxlen=j-i+1;
}
}
}
for (i=1;i<=maxnum;i++)
{
for(int k=ans[i].i;k<=ans[i].j;k++)
ans2[i][k-ans[i].i+1]=first[k];
ans2[i][ans[i].j-ans[i].i+2]=0;
}
int mini=maxnum;
int tmp_len=ans[maxnum].j-ans[maxnum].i+1;
for (i=1;i<=maxnum;i++)
{
if (ans[i].j-ans[i].i+1!=tmp_len ) continue;
if (strcmp(ans2[i]+1,ans2[mini]+1)<0 )
mini=i;
}
if (ans[mini].j-ans[mini].i+1<3)
printf("no significant commonalities\n");
else
printf("%s\n",ans2[mini]+1);
}
return 0;
}