KMP模版带解释过程

KMP算法

当匹配字符串是ababcabaa时,被匹配的字符串是ababababcabaab时
 	q:ababababcabaab
    p:ababcabaa
 先模拟一下简单匹配
    ababababcabaab
    ababcabaa
    11110
    ababababcabaab
     ababcabaa
     0
    ababababcabaab
      ababcabaa
      11110
    .......
匹配过程:
1. 当从被匹配字符串的第一个字符开始与匹配,当被匹配字符串和匹配字符串中的字符不同的时候为0 匹配失败
2. 然后从被匹配字符串的后一个字符开始再与匹配字符串一个个匹配,速度很慢
3. KMP算法可以加速匹配,通过移动匹配字符串
 
KMP算法先处理匹配字符串 计算next数组
1.首先初始化next数组都为-1
2.从匹配字符串下标为1的字符i开始,取出上个字符i-1的next值j,
3.若p[j+1] != p[i]且j!=-1,往前寻找 j=next[j]
4.若p[j+1] == p[i],next[i] = j+1
 
 看一下例子 p=abcaba,默认为-1-1-1-1-1-1
 i = 1 j = next[0] = -1 不满足操作3 p[j+1] != p[i] 不满足操作4 next值不变
 i = 2 j = next[1] = -1 不满足操作3 p[j+1] != p[i] 不满足操作4 next值不变
 i = 3 j = next[2] = -1 不满足操作3 p[j+1] == p[i] 满足操作4 next[i]=j+1 next[3]=0
 i = 4 j = next[3] = 0  p[j+1] == p[i] 不满足操作3 满足操作4 next[i]=j+1 next[4]=1
 i = 5 j = next[4] = 1  p[j+1] != p[i] 满足操作3 j = next[j] = -1 不满足操作3 p[j+1] == p[i] 满足操作4 next[5]=0
 最后next数组为[-1,-1,-1,0,1,0]
 
KMP匹配操作:
1. j从-1开始,遍历被匹配字符串q
2. 若 j != -1 且 p[j+1] != q[i]  则 j= next[j] 调整p的下标继续匹配
3. 若匹配则匹配字符个数++
 
ababcabaa的next数组为[-1,-1,0,1,-1,0,1,2,0]
根据KMP再模拟一下匹配
q   ababababcabaab
p   ababcabaa
    11110
当 j = 3,i = 4 时 p[j+1] != q[i],满足操作2  j= next[j] = 1,于是匹配变成
q   ababababcabaab
p     ababcabaa
       111
继续判断当 j = 1,i = 4时,发现满足操作3,匹配字符++,直到
q   ababababcabaab
p     ababcabaa
      11110
重复之前的操作,找到匹配,发现速度很快
q   ababababcabaab
p       ababcabaa
        111111111
 
模版代码
class Solution {
public:
    bool kmp(const string& q, const string& p) {
        int m = q.size();
        int n = p.size();
        vector<int> next(n,-1);
        for(int i = 1;i < n; i++){
            int j = next[i-1];
            while(j != -1 && p[j+1] != p[i]){
                 j = next[j];
            }
            if(p[j+1] == p[i]){
                next[i] = j+1;
            }
        }
        int j = -1;
        for(int i = 1;i < m-1; i++){
            while(j != -1 && p[j+1] != q[i]){
                j = next[j];
            }
            if(p[j+1] == q[i]){
                j++;
                if(j == n-1){
                    return true;
                }
            }
        }
        return false;
    }
};

今天也是爱zz的一天哦!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值