KMP算法

KMP算法

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

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

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

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

9-18-2019-KMP暴力.png

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

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

s1:ABABABC s2:ABA

第一步:

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

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

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

第二步:

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

9-18-2019-动画kmp.gif

当子串下标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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值