题目链接: 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; }