【算法笔记】——KMP

本文深入解析了KMP算法的求解思路和方法,详细介绍了如何根据已知的next数组值求解新的值,避免了传统模式匹配中的无效位移,提高了匹配效率。文章通过具体的代码示例展示了KMP算法的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

next数组的求解

求解思路

根据前j个已经求得到next值来求next[i+1]。
1.设next[i]的值为k(k为最长前后缀匹配的长度),那么next[i+1]最大为k+1。
反证:假设next[i+1]的值大于k+1,那么一定存在next[i]=k+1,与假设next[i]=k矛盾。
2.如果当前最长前缀寻找失败,那么下一个最长匹配子串只可能出现在前k个元素中,且长度等于next[j]
也可以用反证法求解
3.其他的原理见KMP分析

 

求解方法

设i为当前所求next的下标,j为当前待验证的最长匹配前缀长度(也是和当前求解子串的最后一个元素进行比较的元素)
1.next[0]=-1,作为每次探寻next的结束标志
2.若成功匹配到前缀或者已经探寻结束了,那么令next[i]=j+1;
3.否则,让j=next[j],即让j等于当前长度前缀的最长前缀子串

KMP

1.结束标志:(1)当匹配成功,即遍历完待匹配的串时,即j==sizeof(匹配串)(2)当i==sizeof(主串)且j!=sizeof(匹配串)
代码如下:

#include<string>
#include<iostream>
#include<vector>
using namespace std;

void getnext(string &s,vector<int> &next){
    next[0]=-1;
    int i=1,j=-1;
    while(i<next.size()){
        if(j==-1||s[i-1]==s[j])
            next[i++]=++j;
        else
            j=next[j];
    }
}
int kmp(string &s,string &p){
    vector<int> next(p.size());
    getnext(p,next);
    cout<<"next数组为:"<<endl;
    for(int i=0;i<next.size();i++){
        cout<<next[i]<<' ';
    }
    cout<<endl;
    for(int i=0,j=0;i<s.size();){
        if(s[i]!=p[j]){
            if(j==0) i++;
            else j=next[j];
        }
        else{
            i++;j++;
        }
        if(j==p.size())
            return i-j;

    }
    return -1;
}
int main(){
    string s="abcabaaaabaabcac";
    string p="abaa";
    cout<<"kmp匹配结果为:"<<kmp(s,p)<<endl;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值