欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

KMP算法

程序员文章站 2022-07-14 08:23:44
...

KMP算法

在计算机科学中,Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个主文本字符串`S`内查找一个词`W`的出现位置。此算法通过运用对这个词在不匹配时本身就包含足够的信息来确定下一个匹配将在哪里开始的发现,从而避免重新检查先前匹配的字符

这个算法是由高德纳沃恩·普拉特在1974年构思,同年詹姆斯·H·莫里斯也独立地设计出该算法,最终由三人于1977年联合发表。

简单来说这个算法就是字符串匹配的算法。

比如说这个暴力匹配,不用说在数据大到一定程度绝对超时。

KMP算法

所以我们需要一种更快的算法来匹配,这就是我们的KMP算法

现在我们有字符串s1,s2,需要在s1中寻找s2出现的位置。

s1:ABABABC s2:ABA

第一步:

我们需要得到s2的前缀数组。

(如果你不知道怎么求最长公共前后缀的话可以看看下面这个链接)

https://blog.csdn.net/qq_43597131/article/details/89285932

第二步:

进行匹配,当子串和主串所对应的字符不相同时,主串不动,子串下标i就变为前缀数组next[i]的值,也就是这个位置对应的最长公共前后缀。

KMP算法

当子串下标i等于了子串的长度时,说明匹配成功,j-i+1就是这时匹配的位置,结束之后,i=next[i]继续进行匹配。知道j=主串的长度。

我们给出洛谷模板题代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,k,len1,len2;
int next1[1000001];
char s1[1000001];
char s2[1000001];
inline void get_next() //求出next数组 
{ //next数组是从 S[0到i-1]前子串 的前缀后缀最大值
    int t1=0,t2;
    next1[0]=t2=-1;
    while(t1<len2) 
        if(t2==-1 || s2[t1]==s2[t2]) //类似于KMP的匹配 
            next1[++t1]=++t2;
        else t2=next1[t2];//失配 
} 
inline void KMP() //KMP 
{ 
    int t1=0,t2=0;//从0位开始匹配 
    while(t1<len1) //临界值 
    { 
        if(t2==-1 || s1[t1]==s2[t2]) //匹配成功,继续 
            t1++,t2++;
        else t2=next1[t2]; //失配 
        if(t2==len2) printf("%d\n",t1-len2+1),t2=next1[t2];//t2==lenn2时,匹配成功;t1-len2+1即为第一个字母的位置 
    } //匹配成功后,t2置为next[t2] 
} 
int main(){ 
    scanf("%s",s1);
    scanf("%s",s2);
    len1=strlen(s1);
    len2=strlen(s2);
    get_next();
    KMP();
    for(int i=1;i<=len2;++i) 
        printf("%d ",next1[i]);//输出next数组 
    return 0;
}

再给一个详细的视频教学链接


再给一个详细的视频教学链接

https://www.bilibili.com/video/av11866460?t=1139
相关标签: KMP