版权声明: https://blog.csdn.net/sgh666666/article/details/82425478
题意:
给定n个字符串,要你求出这n个字符串的最长公共子串,如果存在多个输出字典序最小的那个.
分析:
KMP+暴力去枚举即可.
#include<stdio.h>
#include<string.h>
const int maxn = 107;
const int oo = 1e9+7;
char s[maxn][maxn];
int f[maxn];
void getFail(char *P)
{
int m = strlen(P);
f[0] = f[1] = 0;
for(int i = 1; i < m; i++)//虽然字符串是0到m-1,但是要求出f[m]的值
{
int j = f[i];
while(j && P[i] != P[j]) j = f[j];
f[i + 1] = P[i] == P[j] ? j + 1 : 0;
}
}
bool find(char *T, char *P) //找到所有匹配点
{
int n = strlen(T);
int m = strlen(P);
int j = 0;
for(int i = 0; i < n; i++)
{
while(j && T[i] != P[j]) j = f[j];
if(T[i] == P[j]) j++;
if(j == m) return true;//就算j到m了,也用f[m]继续匹配
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int i, j, len, M, MaxLen=60;
char ans[maxn] = "Z";
scanf("%d", &M);
for(i=0; i<M; i++)
scanf("%s", s[i]);
for(len=60; len>=3; len--)
for(i=0; i<=MaxLen-len; i++)
{///枚举第一个串的所有子串
char b[maxn]={0};
strncpy(b, s[0]+i, len);
getFail(b);
for(j=1; j<M; j++)
{
if(find(s[j], b) == false)
break;
}
if(j==M && strcmp(ans, b) > 0)
strcpy(ans, b);
if(ans[0] != 'Z' && i==MaxLen-len)
i=100, len = 0;///跳出循环
}
if(ans[0] == 'Z')
printf("no significant commonalities\n");
else
printf("%s\n", ans);
}
return 0;
}