KMP代码解析

KMP

字符串查找算法:在文本串S中查找模式串P

原题链接

推荐初学者先看这篇大佬博客,讲的超级详细从头到尾彻底理解就KMP

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;

const int N = 1000010;
int m, n;//m是S的长度,n是P的长度

char s[N], p[N];
int ne[N];
//ne[i]表示,在字符串p里,下标为i的字符(第i+1个字符)之前字符串的公共前缀和后缀的最大长度
void KmpSearch(int m, int n, char* p, char* s) {
    int i = 0;
    int j = 0;
    int k = -1;//前缀后缀公共元素的个数
    ne[0] = -1;//设定初始值
    //第一个元素前面没有字符,设为1,
    //第二个元素前面只有一个元素不存在前缀后缀,所以是0
    int slen = m;
    int plen = n;
    //求next数组
    //即p字符串自我匹配的过程
    //j是后缀的下一位,k是前缀的下一位
    /*假设 ne[j]=k  j前面字符串的公共前后缀最大长度为k
    若p[j] == p[k] 公共长度加一
    ne[++j]=++k;
    若p[j]!=p[k] j,k位置失配,那么公共前缀缩短,k回溯到某个位置重新和j处进行匹配,看下面图一
    */
    while (j < plen ) {
        if (k == -1 || p[j] == p[k]) {
            j++;
            k++;
            ne[j] = k;//不优化
        }
        else
            k = ne[k];
    }
  
    //kmp
    j = 0;//清零为kmp做准备

    while (i < slen && j < plen) {
        //如果j==-1,或者当前字符匹配成功,都令i++,j++
        if (j == -1 || s[i] == p[j]) {
            j++;
            i++;
        }
        //匹配不成功,此时的j在公共后缀的下一位,ne[j]是公共前缀的后一位
        //j回调到ne[j]的位置,让ne[j]位置的数和s[i]继续匹配
        //回调匹配的过程相当于字符串向右移动了  j-ne[j] 个位置
        //即 失配时,模式串向右移动的位数为:失配字符所在位置 - 失配字符对应的next值
        //与求ne[]数组不匹配那里同理,可以自己尝试画图
        else {
            j = ne[j]; 
        }
        
        //p串走到最后匹配成功,输出开始匹配的位置

        if (j == plen)
        {
            printf("%d ", i - j);
            j = ne[j];//因为P在S中出现的位置可能有重叠,所以需要回调
        }

    }

}
int main() {

    cin >> n >> p >> m >> s;
    KmpSearch(m, n, p, s);
    return 0;

}

图一:求next数组,出现不匹配情况时, k = ne[k] 语句的图解

k=ne[k]语句图解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值