题意:给两个字符串s1和s2,求一个字符串s,使得s1既是s的子串,s2也是s的子串。
kmp1:包含情况,s1是s2的子串 或者 s2是s1的子串
kmp2:有公共的前缀和后缀(必须一个是前缀,一个是后缀) 即 resita 和 mures 的公共部分是3,aza 和 zaz 的公共部分是2(后台数据水了,有的代码这组样例输出2也A了)
kmp2的前提就是没有包含关系了,那么其前缀是公共部分的字符串就是模式串了,保证一直匹配到s2的最后,都不会达到i==strlen(s1),因为不存在包含关系。
所以达到j==strlen(s2)的时候就是匹配的最大公共部分了~
这道题与2594很像~
View Code
1 #include <stdio.h> 2 #include <string.h> 3 const int N=1000005; 4 char s[2][N]; 5 int len[2]; 6 int next[2][N]; 7 int max(int a,int b){return a>b?a:b;} 8 void getNext(int v){ 9 int i=0,j=-1; 10 next[v][0]=-1; 11 while(i<len[v]){ 12 if(j==-1||s[v][i]==s[v][j]) { 13 i++;j++; 14 next[v][i]=j; 15 } 16 else j=next[v][j]; 17 } 18 } 19 int kmp1(int u,int v){ 20 int i=0,j=0; 21 while(i<len[u]&&j<len[v]){ 22 if(j==-1||s[u][i]==s[v][j]){ 23 i++;j++; 24 }else j=next[v][j]; 25 } 26 if(j>=len[v]) return 1; 27 return 0; 28 } 29 30 int kmp2(int u,int v){ 31 int i=0,j=0; 32 while(i<len[u]){ 33 if(i==-1||s[u][i]==s[v][j]){ 34 i++;j++; 35 if(j>=len[v]) return i; 36 }else i=next[u][i]; 37 } 38 return 0; 39 } 40 int main(){ 41 int i,j,t; 42 scanf("%d",&t); 43 while(t--){ 44 scanf("%s %s",s[0],s[1]); 45 46 len[0]=strlen(s[0]); 47 len[1]=strlen(s[1]); 48 getNext(0); 49 getNext(1); 50 51 if(len[0]>=len[1]&&kmp1(0,1)) { 52 printf("%d\n",len[0]); 53 } 54 else if(len[0]<len[1]&&kmp1(1,0)) { 55 printf("%d\n",len[1]); 56 } 57 else{ 58 printf("%d\n",len[0]+len[1]-max(kmp2(0,1),kmp2(1,0))); 59 } 60 } 61 return 0; 62 }