poj 3080 Blue Jeans (KMP+最长公共子串)
题目大意: 给定n个字符串,找出最长的公共子串,不存在输出 no significant commonalities解题思路: 选出长度最短的字符串,枚举它的子串
把它的子串分别与其余的n-1个字符串匹配
字符串长度越短它的子串就越少,枚举量越少
枚举子串的顺序从大到小,能够匹配就退出输出答案
如果从小到大枚举则需要枚举所有符合情况的子串,耗费时间
代码:
#include <stdio.h> #include <algorithm> #include <string.h> #include <stdlib.h> #define Max 70 #define INF 0x3f3f3f3f using namespace std; int Long[Max],Next[Max]; char ch[Max][Max]; struct snode{ char ch3[Max]; }chtemp[Max]; bool cmp(struct snode a,struct snode b) { int temp=strcmp(a.ch3,b.ch3); if(temp>=0) return 0; return 1; } void Get_next(char ch1[],int Tlen) { int i=0,j=-1; Next[0]=-1; while(i<Tlen) { if(j==-1||ch1[j]==ch1[i]) { i++; j++; Next[i]=j; } else j=Next[j]; } } int Kmp(char ch1[],int ii,int Tlen) { int i=-1,j=-1; while(i<Long[ii]&&j<Tlen) { if(j==-1||ch1[j]==ch[ii][i]) { i++; j++; } else j=Next[j]; } if(j>=Tlen) return 1; return 0; } int main() { char ch1[Max]; int min,mini,t,i,j,j1,j2,temp,n,m,k,pd,pdi,End; scanf("%d",&t); while(t--) { min=INF; memset(ch,0,sizeof(ch)); scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%s",ch[i]); temp=strlen(ch[i]); Long[i]=temp; if(temp<min) min=temp,mini=i; } for(i=Long[mini],pd=0,m=0;i>=3;i--) { End=Long[mini]-i; for(j=0;j<=End;j++) { memset(ch1,0,sizeof(ch1)); for(j1=j,j2=0;j2<i;j2++,j1++) { ch1[j2]=ch[mini][j1]; } ch1[j2]='\0'; memset(Next,0,sizeof(Next)); Get_next(ch1,i); for(j1=1,k=1;j1<=n;j1++) { if(j1==mini) continue; if(Kmp(ch1,j1,i)) { k++; } else break; } if(k==n) { strcpy(chtemp[m++].ch3,ch1); pd=1; pdi=i; } } if(pd==1) { sort(chtemp,chtemp+m,cmp); printf("%s\n",chtemp[0].ch3); break; } } if(pd==0) printf("no significant commonalities\n"); } return 0; }
补充:软件开发 , C++ ,