POJ 3080 (暴力KMP解最长连续公共自序列)
题目链接:http://poj.org/problem?id=3080
题意:1.给m个长度为60的字符串,找他们连续最长自序列
2.如果给子序列长度小于3,则不输出。
3.相同长度,输出字典序小的
题解:1.暴力KMP,枚举第一个字符串的所有自序列
2.相同长度的,用strcmp函数找小的。
代码如下:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 char s[20][65]; 7 char t[65],a[65]; 8 char get[65]; 9 int Next[100]; 10 int begin,end,maxx; 11 void getstr(int begin,int end, int len) 12 { 13 for(int j=0,i=begin;i<=end;i++,j++) 14 { 15 t[j]=a[i]; 16 } 17 } 18 void getNext(int len) 19 { 20 int i=0; 21 int j=-1; 22 Next[0]=-1; 23 while(i<len) 24 { 25 if(j==-1||t[i]==t[j]) 26 { 27 i++; 28 j++; 29 Next[i]=j; 30 } 31 else 32 { 33 j=Next[j]; 34 } 35 } 36 } 37 38 int find(int z,int len1,int len2) 39 { 40 int i=0,j=0; 41 while(j<len2&&i<len1) 42 { 43 if(j==-1||s[z][i]==t[j]) 44 { 45 i++;j++; 46 } 47 else 48 { 49 j=Next[j]; 50 } 51 if(j==len2) 52 { 53 return 1; 54 } 55 } 56 return 0; 57 } 58 int main() 59 { 60 int test; 61 cin>>test; 62 while(test--) 63 { 64 int tttt=0; 65 int n; 66 scanf("%d",&n); 67 for(int i=0;i<n;i++) 68 { 69 scanf("%s",s[i]); 70 } 71 strcpy(a,s[0]); 72 int temp; 73 int tt=0; 74 for(int i=60;i>0;i--) //遍历长度 75 { 76 int l=i;int ttt=0; 77 for(int j=60-i;j>=0;j--)//该长度所有的子串 78 { 79 memset(t,0,sizeof(t)); 80 getstr(j,l+j-1,l); 81 getNext(l); 82 for(int k=1;k<n;k++) //子串匹配 83 { 84 temp=find(k,60,l); 85 if(temp==0) 86 break; 87 } 88 if(temp==1) 89 { 90 tt=1; 91 if(!ttt) 92 { 93 strcpy(get,t); 94 ttt=1; 95 } 96 else if(ttt) 97 { 98 if(strcmp(t,get)<0) 99 { 100 memset(get,0,sizeof(get)); 101 strcpy(get,t); 102 } 103 } 104 } 105 } 106 if(tt) 107 { 108 int ll=strlen(t); 109 if(ll>=3) 110 { 111 tttt=1; //tttt来防止匹配失败,即没有公共子串的情况 112 cout<<get<<endl;break; 113 } 114 else 115 { 116 tttt=1; 117 cout<<"no significant commonalities"<<endl;break; 118 } 119 } 120 } 121 if(!tttt) 122 cout<<"no significant commonalities"<<endl; 123 } 124 }
浙公网安备 33010602011771号