题目链接: poj 1226
题目大意: 给出N个字符串,找出一个最长的子串
使得它和N个字符串正向或者逆向匹配,输出长度
解题思路: 如果这个字串存在,那么它必定存在与N个字符串中最小的那个串
找到N个字符串中最小的串,然后枚举最小串的所有子串
从最长的子串开始枚举,长度逐渐减少
只要存在这样的子串和其他的字符串匹配,当前长度就是最优解
代码:
//Final Kmp找出最长的字串使得正向或者逆向匹配所有给出的字符串
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 110
#define INF 0x3f3f3f
int Long[MAX],n,mini,min;
char ch[MAX][MAX];
void Getnext(char temp[],int *next,int Tlen)
{
int i=0,j=-1;
*next=-1;
while(i<Tlen)
{
if(j==-1||temp[i]==temp[j])
{
i++; j++;
*(next+i)=j;
}
else
j=*(next+j);
}
}
int Kmp(char temp[],int *next,int Tlen,int ii)
{
int i=-1,j=-1;
while(i<Long[ii]&&j<Tlen)
{
if(j==-1||temp[j]==ch[ii][i])
{
i++,j++;
}
else
j=next[j];
}
if(j>=Tlen)
return 1;
return 0;
}
int main()
{
int m,t,k,i,j,j1,i1,a,b,pd;
scanf("%d",&t);
while(t--)
{
min=INF;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%s",ch[i]);
Long[i]=strlen(ch[i]);
if(min>Long[i]) //找到最短的那个串
min=Long[i],mini=i;
}
for(i=Long[mini];i>=1;i--) //从最长的字串开始枚举
{
for(j=0;j+i<=Long[mini];j++)
{
char temp[MAX]={0},temp1[MAX]={0};
int next[MAX]={0},next1[MAX]={0};
pd=0;
for(j1=0;j1<i;j1++)
{
temp[j1]=ch[mini][j+j1];
}
temp[j1]='\0';
for(j1=0;j1<i;j1++)
{
temp1[j1]=ch[mini][j+i-j1-1];
}
temp1[j1]='\0';
Getnext(temp,next,i); //正向串前缀数组
Getnext(temp1,next1,i); //逆向串前缀数组
k=1;
for(i1=1;i1<=n;i1++)
{
if(i1==mini)
continue;
if(Kmp(temp,next,i,i1)||Kmp(temp1,next1,i,i1)) //正向逆向匹配
{
k++;
}
else
break;
}
if(k==n) //找到当前最长的字串就退出,停止搜索
{
pd=1;
printf("%d\n",i);
break;
}
}
if(pd==1)
break;
}
if(!pd) //找不到字串
printf("0\n");
}
return 0;
}