KMP算法

 

算法流程

我们称A串为主串(母串),用来匹配的B串为模式串。

我们用指针i,j表示A[i-j+1...i]与B[1...j]的值完全相等

若A[i+1]==b[j+1] i++,j++;

否则减少j的值来保证A[i],B[j]仍然满足以上关系

j减少为j' 合法的j'应当满足B[1...j']与B[j-j'+1...j]的值完全相等

发现j'的取值只与B[j]相关

所以我们可以预处理出一个p[j]表示匹配到B串的第j个字母而第j+1个字母不能匹配时,最大的j'取多少

怎么预处理出p[]呢

假设我们现在已经知道了p[1..i-1]要求p[i]

若B[i+1]==p[i-1]+1 p[i]=p[i-1]+1

否则再看B[i+1]是否等于p[p[i-1]]+1 就一直这样子就可以啦

 

做题

HDU2087 剪花布条

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define R register
 5 #define go(i,a,b) for(R int i=a;i<=b;i++)
 6 #define yes(i,a,b) for(R int i=a;i>=b;i--)
 7 #define ll long long
 8 #define db double
 9 using namespace std;
10 const int N=1005;
11 char a[N],b[N];
12 int lena,lenb,ans,p[N];
13 void init()
14 {
15     p[1]=0;
16     go(i,2,lenb)
17     {
18         int c=p[i-1];
19         while(c&&b[i]!=b[c+1])c=p[c];
20         if(b[i]==b[c+1])p[i]=c+1;else p[i]=0;
21     }
22 }
23 int main()
24 {
25     while(1)
26     {
27         cin>>(a+1);if(a[1]=='#')break;
28         cin>>(b+1);ans=0;
29         lena=strlen(a+1),lenb=strlen(b+1);
30         init();
31         int j=0;
32         go(i,0,lena)
33         {
34             while(j&&a[i+1]!=b[j+1])j=p[j];
35             if(a[i+1]==b[j+1])j++;
36             if(j==lenb){ans++;j=0;}
37         }
38         printf("%d\n",ans);
39     }
40     return 0;
41 }
View Code

吐槽一下这题数据好水,开始我把init()函数注释掉了都AC了

 POJ2406 Power Strings

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define R register
 5 #define go(i,a,b) for(R int i=a;i<=b;i++)
 6 #define yes(i,a,b) for(R int i=a;i>=b;i--)
 7 #define ll long long
 8 #define db double
 9 using namespace std;
10 int rd()
11 {
12     int x=0,y=1;char c=getchar();
13     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
14     while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
15     return x*y;
16 }
17 const int N=1000005;
18 char a[N];
19 int p[N],len;
20 void sol()
21 {
22     p[1]=0;
23     go(i,2,len)
24     {
25         int b=p[i-1];
26         while(b&&a[i]!=a[b+1])b=p[b];
27         if(a[i]==a[b+1])p[i]=b+1;else p[i]=b;
28                 //注意else这一步是因为多组数据,p[i]的初始值不一定为0
29     }
30 }
31 int main()
32 {
33     while(1)
34     {
35         scanf("%s",a+1);if(a[1]=='.')break;
36         len=strlen(a+1);sol();
37         if(len%(len-p[len])==0)printf("%d\n",len/(len-p[len]));
38         else printf("1\n");
39     }
40     return 0;
41 }
42             
View Code

 

posted @ 2019-02-16 15:40  DTTTTTTT  阅读(157)  评论(0编辑  收藏  举报