。。。。数据太小,就直接用暴力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; }