hdu1841 kmp

题意:给两个字符串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 }

 

posted @ 2013-02-11 01:08  _sunshine  阅读(306)  评论(0编辑  收藏  举报