【算法基础】KMP算法

如果要匹配一个字符串,例如我们要匹配s[m]中哪些位置可以匹配p[n],暴力的做法应该是对s[m]中的所有位置遍历,每个位置都匹配一遍,这样做是可以,但是效率很低。如果我们在每个位置匹配的时候能够利用好已经部分匹配好的信息,例如s[i-1]和p[j]和前面的都匹配好了,但是是s[i]和p[j+1]不匹配,可以利用前面匹配好的部分对j进行跳转,这就是KMP算法的核心所在。

ne数组:首先我们都规定,数组下标都从1开始,next数组的含义即——

对next[ j ] ,是p[ 1, j ]串中前缀和后缀相同的最大长度(部分匹配值), 即 p[ 1, next[ j ] ] = p[ j - next[ j ] + 1, j ]这样在出现上面的情况时(s[i-1]和p[j]和前面的都匹配好了,但是是s[i]和p[j+1]不匹配)就可以对j进行跳转:j=ne[j]

怎么求ne数组:这就需要让p数组自己匹配自己,从最开始匹配肯定时没问题的所以应该是从2开始,即i从2开始,j从0开始,让j指向的取匹配i指向的。

下面是详细的代码:

#include<iostream>

using namespace std;
const int N=1e5+10;
const int M=1e6+10;
char p[N],s[M];
int ne[N];
int main()
{
    int n,m;
    cin>>n>>p+1>>m>>s+1;
    
    //ne[n]=0因为整个p数组的最大前缀和后缀就是p数组本身
    //i所指的是后缀,j所指的是前缀
    //j所指的匹配取匹配i所指的
    for(int i=2,j=0;i<=n;i++)
    {
        //不匹配,则对j进行跳转,如果j为0,则不存在前缀和后缀相等的情况
        //也就是说需要重新匹配,需要跳转到最开始.
        while(j&&p[i]!=p[j+1])j=ne[j];
        if(p[i]==p[j+1])j++;
        ne[i]=j;
    }
    
    for(int i=1,j=0;i<=m;i++)
    {
        while(j&&s[i]!=p[j+1])j=ne[j];
        if(s[i]==p[j+1])j++;
        if(j==n)cout<<i-j<<' ';
    }
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值