今天对KMP的认识又加深一点了,可是又不是很能用语言来表达!
题目大意:给定两个字符串,比如abcd,dcab,需要把它连接起来,但是需要遵循两个条件,1 最短原则 2 长度相同的前提下字典序的优先
连接原则:如果第一个字符串的后缀(长度为n)和第二个字符串的前缀(长度为n)相同,那么连接的时候可以省去相同的n个字符,本来有2n个字符;
仍然以上面的两个字符串为例,有两种连法,abcdcab和dcabcd,显然第二个字符串更短,所以输出dcabcd;
解决办法:两次KMP
运用一次KMP可以计算出两个字符串的前缀和后缀的相同长度n;
两次KMP后比较n的值即可;
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 #define N 100005 6 char s1[N],s2[N]; 7 int next[N]; 8 void get_next(char *str) 9 { 10 int i=0,j=-1; 11 next[0]=-1; 12 int len=strlen(str); 13 while(i<len) 14 { 15 if(j==-1||str[i]==str[j]) 16 { 17 i++; 18 j++; 19 next[i]=j; 20 } 21 else 22 j=next[j]; 23 24 } 25 26 27 } 28 int KMP(char *str1,char *str2,int next[]) 29 { 30 int i=0,j=0; 31 int len1=strlen(str1); 32 // int len2=strlen(str2); 33 while(i<len1)//这里循环的应用根据不同的要求可以计算出符合条件的J值 34 { 35 //i要循环到len1而不是按照KMP的算法要求j,是因为我们需要计算str1的末尾 36 if(j==-1||str1[i]==str2[j]) 37 { 38 39 i++; 40 j++; 41 } 42 else 43 j=next[j]; 44 45 } 46 return j; 47 48 } 49 int main() 50 { 51 while(scanf("%s %s",s1,s2)!=EOF) 52 { 53 54 memset(next,0,sizeof(next)); 55 get_next(s2); 56 int c_1=KMP(s1,s2,next); 57 memset(next,0,sizeof(next)); 58 get_next(s1); 59 int c_2=KMP(s2,s1,next); 60 if(c_1==c_2) 61 { 62 63 if(strcmp(s1,s2)<0) 64 { 65 66 printf("%s%s\n",s1,s2+c_1); 67 } 68 else 69 { 70 71 printf("%s%s\n",s2,s1+c_2);; 72 73 } 74 } 75 else{ 76 if(c_1>c_2) 77 { 78 printf("%s%s\n",s1,s2+c_1); 79 80 } 81 else{ 82 printf("%s%s\n",s2,s1+c_2); 83 } 84 } 85 86 87 88 } 89 return 0; 90 91 }
hdu 2594 (Simpsons’ Hidden Talents)
和上面的题目一样只是没有上面那一题复杂,只需要一次KMP即可;
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 #define N 50004 6 char s1[N],s2[N]; 7 int next[N]; 8 int len1,len2; 9 void get_next() 10 { 11 12 int i=0,j=-1; 13 next[0]=-1; 14 while(i<len1) 15 { 16 17 if(j==-1||s1[i]==s1[j]) 18 { 19 i++; 20 j++; 21 next[i]=j; 22 23 } 24 else 25 j=next[j]; 26 } 27 } 28 int KMP() 29 { 30 31 int i=0,j=0; 32 get_next(); 33 while(i<len2) 34 { 35 if(j==-1||s2[i]==s1[j]) 36 { 37 38 i++; 39 j++; 40 } 41 else 42 j=next[j]; 43 44 } 45 return j; 46 } 47 int main() 48 { 49 50 while(scanf("%s",s1)!=EOF) 51 { 52 len1=strlen(s1); 53 scanf("%s",s2); 54 len2=strlen(s2); 55 memset(next,-1,sizeof(next)); 56 int ans; 57 ans=KMP(); 58 // printf("%d\n",ans); 59 if(ans==0) 60 printf("0\n"); 61 else 62 { 63 int i; 64 for(i=0;i<ans;i++) 65 { 66 printf("%c",s1[i]); 67 } 68 printf(" %d\n",ans); 69 } 70 71 72 73 74 75 } 76 return 0; 77 }