KMP

KMP

KMP算法,又称模式匹配算法,能够在线性时间内判定字符串A是否为B的子串,并求出字符串AB各次出现的位置。

O(nm)算法

这种算法就是暴力枚举算法
枚举字符串B中的每一个位置i,把字符串A与字符串B的后缀B[i~m]向后逐一扫描比较A[1]与B[i]…是否相等,我们们把这种比较过程称为匹配
这种算法的时间复杂度会很高,所以不可取

O(n+m)算法 KMP

KMP算法的算法精髓在于,对于每一次失配之后,我都不会从头开始重新进行枚举,这样太傻了,而是根据我已经知道的数据,从某个特定的位置开始匹配;而对于模式串的每一位,都有唯一的特定变化位置,这个失配之后的特定位置开始匹配,这样有利于不用从头匹配,节约时间
比如我们看看一组数:
abcab
abcacababcab
我们看,匹配到 前四位成功了,但是第五位就不行了,所以我们就把它移动到失配的那一位,简单的想,我们已经遍历过的字符重合,导致我们没必要再移动了,直接进行移动就好了
所以我们就明白了,KMP的思想就是用失配数组来确定某一位失配时,我们可以将前一位跳跃之前匹配过的某一位。
但是我们还要思考一个问题:
1.我们失配数组应建立在模式串意义下,而不是文本串,因为我们要把模式串进行移动变灵活
2.怎么构造失配数组,怎么确定位置?
首先我们明白,基于先决条件1我们知道应当考虑模式串的第i为失配时,应该跳到哪里?因为在文本中,之前匹配的所有字符已经没有用了,所以我们的失配数组应当记录:

在模式串中对于每一位i,他的失配数组kmp数组应当记录的是一个j,并且s1i=s1j并且j!=1时满足s11~s1 j-1 分别和 s1(i-j+1)~s1(i-1)
上面的就是移动位法则

KMP中前后缀不包括模式串的本身,只考虑真前缀后缀,因为模式串本身需要整体 考虑,并且,匹配完这个串后,匹配整个串不久完成了
1.模式串进行自我匹配
2.ab进行匹配

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#define MAXN 1000010
using namespace std;
int kmp[MAXN];
int la,lb,j; 
char a[MAXN],b[MAXN];
int main()
{
    cin>>a+1;
    cin>>b+1;
    la=strlen(a),lb=strlen(b);
    for (int i=2;i<=lb;i++)//自我进行匹配
    {     
        while(j&&b[i]!=b[j+1]) j=kmp[j];//匹配不成功,回跳,直至能匹配为止    
        if(b[j+1]==b[i])j++;  //匹配成功  
        kmp[i]=j;//失配后接着跳
    }
    j=0;//匹配的位置
    for(int i=1;i<=la;i++)
    {//ab进行匹配
        while(j>0&&b[j+1]!=a[i]) j=kmp[j];//匹配不成功,接着跳
        if (b[j+1]==a[i]) 
            j++;//匹配成功,下一位 
        if (j==lb) {cout<<i-lb+1<<endl;j=kmp[j];}//重新进行匹配
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值