KMP

推荐blog:

https://www.luogu.com.cn/blog/pks-LOVING/zi-fu-chuan-xue-xi-bi-ji-qian-xi-kmp-xuan-xue-di-dan-mu-shi-chuan-pi-post

http://www.matrix67.com/blog/archives/115(先看这些blog)

 

首先,普通字符串匹配是一个一个进行匹配,配不上了,就将整个字符串往后挪一位,再从头开始匹配,大概就像这样:

 

 

但这样的时间复杂度为O(nm);

而KMP这不一样,下面我来演示以下:

大概是这样的两个串

接下来进行匹配

比如粉色代表匹配成功,但在下一位匹配时却匹配失败了,按照普通的搞法,应该是将b往后挪一位,咱们从头再来,但kMP却是这样的:

我们发现标蓝的部分相同(当前匹配位置的后缀与前缀相同的最长部分),那么,我们可以直接将b蓝色的前一部分,挪到后一部分蓝色,就像这样

然后继续往后进行匹配,反复这些操作,直至找到一次完全匹配,然后再继续匹配

如何迅速找到当前位置border的最大长度呢(注:border就是一个串前缀和后缀相等部分的最大长度)

可以自己先跟自己匹配,用一个数组next[i]来表示位置i的boder的长度

 

自己怎么跟自己匹配?自己跟自己不是一样的吗?(迷惑)

没有关系,既然知道自己跟自己匹配时从第一位开始匹配是一样的,那用自己的第二位与自己的第一位开始匹配就可以了

推荐题:洛谷P3375

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int kmp[1000006];
 4 char a[1000006],b[1000006];
 5 int main(){
 6     int lena,lenb,i,j;
 7     cin>>a+1>>b+1;
 8     lena=strlen(a+1);lenb=strlen(b+1);
 9     j=0;
10     for(i=2;i<=lenb;i++){
11         while(j&&b[j+1]!=b[i])j=kmp[j];
12         if(b[j+1]==b[i])j++;
13         kmp[i]=j;
14     }j=0;
15     for(i=1;i<=lena;i++){
16         while(j&&b[j+1]!=a[i])j=kmp[j];
17         if(b[j+1]==a[i])j++;
18         if(j==lenb){
19             cout<<i-lenb+1<<endl;
20             j=kmp[j];
21         }
22     }
23     for(i=1;i<=lenb;i++)cout<<kmp[i]<<" ";
24     return 0;
25 }

 

posted @ 2020-08-22 21:21  Jessica_Cao  阅读(349)  评论(0编辑  收藏  举报