题目链接:http://poj.org/problem?id=3080
求给定多个字符串的最长公共子串,若有相同输出字典序最小的那个
因为每个串最多60个字符,枚举其中一个串的子串进行匹配并记录最大值即可。
#include <stdio.h>
#include<cstring>
#include<string>
using namespace std;
char ans[70];
char a[12][70],b[70];
int la[12],lb,lans;
int nxt[70];
void gnx(){
memset(nxt,0,sizeof(nxt));
int i=0,j=-1;
nxt[0]=-1;
while(i<lb){
if(j==-1||b[i]==b[j])nxt[++i]=++j;
else j=nxt[j];
}
}
int kmp(int no,int llb){
int i=0,j=0;
while(i<la[no]&&j<llb){
if(j==-1||a[no][i]==b[j])i++,j++;
else j=nxt[j];
}
if(j==llb)return 1;
return 0;
}
int les(char bb[],int len){
int flag=0;
if(len>lans)return 1;
if(len<lans)return 0;
for(int i=0;i<len;i++){
if(bb[i]<ans[i])return 1;
if(bb[i]>ans[i])return 0;
}
return 0;
}
int main(void)
{
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",a[i]);
la[i]=strlen(a[i]);
}
lans=0;
for(int i=0;i<la[1];i++){
strcpy(b,a[1]+i);
lb=la[1]-i;
gnx();
for(int j=1;j+i<=la[1];j++){
int flag=1;
for(int k=2;k<=n;k++){
if(!kmp(k,j)){
flag=0;
break;
}
}
if(flag){
if(les(b,j)){
for(int k=0;k<j;k++){
ans[k]=b[k];
}
ans[j]=0;
lans=j;
}
}
}
}
if(lans>=3)printf("%s\n",ans);
else puts("no significant commonalities");
}
return 0;
}
其实这个写的慢了。。。只需要枚举开头匹配,然后边匹配边更新就好了,复杂度会低一个级别,早期写的懒得改了。。。