Description
Input
Output
Sample Input
3 2 GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 3 GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA GATACTAGATACTAGATACTAGATACTAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA GATACCAGATACCAGATACCAGATACCAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA 3 CATCATCATCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ACATCATCATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AACATCATCATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
Sample Output
no significant commonalities AGATAC CATCATCAT
题目大意:找多个字符串中的最长公共连续子串,如果长度相同,则选取字典序最小的
解题思路:暴力大法。首先找出最短的串,枚举这个串的所有子串,让其与每一个字符串进行匹配,如果匹配成功,则说明这个子串是一个可能的解。
优化策略:首先,匹配的时候用KMP,其次,枚举子串先枚举最长的,这样一旦找到就不用枚举更短的了,比较字典序可以用strcmp。
代码:
#include <iostream> #include <stdio.h> #include <string.h> #define MAX 70 using namespace std; int Next[MAX]; char str[11][70]; char ans[MAX]; void get_next(char x[],int m,int Next[]) { int i,j; j=Next[0]=-1; i=0; while(i<m) { while(-1!=j&&x[i]!=x[j]) j=Next[j]; if(x[++i]==x[++j]) Next[i]=Next[j]; else Next[i]=j; } } bool kmp(char x[],int m,char y[],int n) { int i,j; get_next(x,m,Next); i=j=0; while(i<n) { while(-1!=j&&y[i]!=x[j]) j=Next[j]; i++; j++; if(j>=m) return true; } return false; } int main() { int t,n,min_l,min_p; int i,j,k,l; bool flag; char tmp[70]; scanf("%d",&t); while(t--) { flag=false; min_l=MAX; min_p=0; scanf("%d",&n); for(i=0; i<n; i++) { scanf("%s",str[i]); if(min_l>strlen(str[i])) { min_l=strlen(str[i]); min_p=i; } } for(i=min_l; i>=3&&flag==false; i--) //枚举长度 { for(j=0; j<=min_l-i; j++) //枚举子串 { for(l=j; l<i+j; l++) tmp[l-j]=str[min_p][l]; tmp[l]='\0'; for(k=0; k<n; k++) //逐个匹配 { if(k==min_p) continue; if(kmp(tmp,i,str[k],strlen(str[k]))==false) break; } if(k>=n) { if(flag==false) { flag=true; strcpy(ans,tmp); } else { if(strcmp(ans,tmp)>0) strcpy(ans,tmp); } } } } if(flag==true) printf("%s\n",ans); else printf("no significant commonalities\n"); } return 0; }