题意:是否存在一个长度大于等于3的字符串是所有给出字符串的子串
题目思路:找出第一个字符串所有的子串,用kmp去匹配,因为字符串长度只有60,所以时间复杂度还是很理想的, o(60*60*m*(60+60))= o(10^6);
细节看代码注释
题目链接:http://poj.org/problem?id=3080
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s[20][100], a[100], f[100];
int m;
bool flag;
struct node
{
char s[100];
int len;
/*bool operator<(const node &rhs) const
{
if(rhs.len != len)
return rhs.len > len;
else
return strcmp(rhs.s, s)<0;
}*/
} ans[1000000];//这里一定要开大点,毕竟有可能出现很多匹配第字符串
bool cmp(const node &e, const node &f)
{
if(e.len!=f.len)
return e.len>f.len;
else
return (strcmp(e.s, f.s) < 0);//调试到这里错了,以后记住,有可能数组开小了
}
void getfail(const char *s) //得到失配函数
{
f[0] = 0, f[1] = 0;
int j, len = strlen(s);
for(int i=1; i<len; i++)
{
j = f[i];
while(j && s[i]!=s[j]) j = f[j];
f[i+1] = s[i]==s[j]?j+1:0;
}
}
bool kmp(const char *p) //看是否和所有字符串匹配
{
bool flag1;
int len, len1 = strlen(p);
for(int k=1; k<m; k++)
{
flag1 = true;
len = strlen(s[k]);
for(int i=0, j=0; i<len; i++)
{
while(j && p[j]!=s[k][i]) j = f[j];
if(p[j] == s[k][i]) j++;
if(j == len1)
{
flag1 = false;
break;
}
}
if(flag1) return false;
}
return true;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &m);
for(int i=0; i<m; i++)
scanf("%s", s[i]);
int len = strlen(s[0]);
flag = false;
int cnt = 0;
for(int i=0; i<len-3; i++)
{
for(int j=i+2; j<len; j++)
{
strncpy(a, s[0]+i, j-i+1);
a[j-i+1] = '\0';//strncpy不会自动添加,要手动添加
getfail(a);
if(kmp(a))//用a去匹配1到m-1所有的字符串
{
flag = true;
strcpy(ans[cnt].s, a);
ans[cnt++].len = j-i+1;
}
}
}
if(flag)
{
sort(ans, ans+cnt, cmp);//按要求排序
printf("%s\n", ans[0].s);
}
else puts("no significant commonalities");
}
return 0;
}