kmp算法讲解

本文介绍了KMP算法,一种通过利用匹配失败信息减少字符串比较次数的高效算法。重点讲解了next数组的作用和如何构建,以及其在匹配过程中的应用,以降低最坏时间复杂度至O(m+n)。
摘要由CSDN通过智能技术生成

当我们在进行两个字符串判断时,我们最坏的打算的时间复杂度是n*m

这将会导致我们的时间是与给定的字符串挂钩的

那么,如何缩短判定时间呢


KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)

next数组解释

什么是next数组,可以想象一下,当你在匹配时,以 i 为起点,匹配了 j-1个字符,但是第j个字符的时候,匹配的字符不相同,那该怎么办,这个匹配的字符串假设还有利用价值,也就是说,以i为起点,j为长度的字符串在后缀有存在于匹配字符串的子串时,是还有剩余价值的,这个时候,可以转到最大的前缀,这时候,当前的k应该为匹配的开头

如何实现nx数组

因为我们是匹配字符串,所以要在需要匹配的字符串种做操作,那么如何去做呢

因为我们现在在匹配过程中,如果出现当前位置字符不同的时候,只需要看当前位置我们能匹配长度为 l 的最大的前缀后缀的长度即可

//以下代码基于字符串从0开始c++版本 s2代表匹配字符串
for(int i=1,j=0;s2[i];i++)
{
    //初始的时候,待匹配字符的下标应该是1,因为我匹配下标一直是从0开始(最大前缀)
    while(j&&s2[i]!=s2[j])j=nx[j-1];//j代表当前匹配到的字符,如果说现在你的两个位置字符不能匹配,那么我就需要向之前位置的转移
    if(s2[i]==s2[j])j++;//如果当前我能进行匹配,长度加一
    nx[i]=j;//最后,顶下我当前位置的长度
}

匹配过程

//以下代码基于字符串从0开始c++版本 s1代表待匹配字符串
for(int i=0,j=0;s1[i];i++)
    {
    //i代表s1现在为止的下标
    //现在要对于你两个位置进行匹配,我待匹配字符串一定是不洞的,看我匹配字符串能否匹配
        while(s1[i]!=s2[j]&&j)j=nx[j-1];
        if(s1[i]==s2[j])j++;
        //如果可以就break,这里看题目意思
        if(j==s2.size())break;
    }

总体code

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+7;
int nx[N];
int main()
{
    string s1,s2;
    cin>>s1>>s2;
    for(int i=1,j=0;s2[i];i++)
    {
        while(j&&s2[i]!=s2[j])j=nx[j-1];
        if(s2[i]==s2[j])j++;
        nx[i]=j;
    }
    int ans=0;
    for(int i=0,j=0;s1[i];i++)
    {
        while(s1[i]!=s2[j]&&j)j=nx[j-1];
        if(s1[i]==s2[j])j++;
        if(j==s2.size())
        {
            cout<<"yes";
            return 0;
        }
    }
    cout<<"no";
    return 0;
}

2024.2.4

训练!!!

训练!!!训练!!!训练!!!

训练!!!训练!!!训练!!!训练!!!训练!!!

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值