KMP的一种实现方法(不涉及算法讲解)

KMP的一种实现方法(不涉及算法讲解)

csdn上有很多很多关于KMP的讲解,下面是一种实现方法,因为很多文章已经分析的非常透彻,所以这篇文章主要是对代码的解析为主


B站天勤的KMP算法讲解,这个是链接天勤KMP
这个视频对于算法的思想有着一个很清晰的概括,但是没有实现

哈顿之光大佬的KMP解析数据结构KMP算法配图详解(超详细)


前言


以下是本篇文章正文内容,下面案例可供参考

代码实现

1.获得next数组

next[i]代表i位置匹配成功,但是i+1位置失配,i位置最长匹配的前缀位置

代码如下:

void getnext(const char *t, int *next) {
    next[0] = -1;
    int j = -1;
    //j纪录的是上一个数组中的数字所对应的值
    //可能这样描述很难理解,以一个字符串为例 a b a b
    //在next[0]位置我直接赋值为-1,因为对于只有一个字符来说,寻找它的前后缀都是它本身,没有任何意义
    //接下来。进入循环
    for (int i = 1; t[i]; i++) {
    //以第二个b为例,如果j == -1,也就是说我的上一个字符没法构成任何的相同前缀后缀
    //所以对t[j + 1] 是否等于t[i]进行判断,因为之前的序列中,没有任何前缀后缀,所以只需要看一下当前的i是否等于j + 1位置的字符,很显然,不等于,所以j还是-1
        while(j != -1 && t[j + 1] != t[i]) j = next[j];
        //接下来是还是a,因为j = -1的缘故,所以直接判断是否等于j + 1,相等,所以此时j == 0
        if (t[j + 1] == t[i]) j += 1;
        next[i] = j;
    }
}
//上面说完了所有j == -1的情况,接下来是j  != -1的情况,这一次可以进入while循化了
//并且直接将t[j  + 1] 和 t[i]做对比,之所以这样,是因为直接看能否接续next[i - 1]的后缀
//如果不行的话,就会不断的向前去寻找能和此字符匹配上的情况,如果没有,在while结束它将回到-1

2.kmp

代码如下:

int kmp(const char *s, const char *t) {
    int n = strlen(t);
    int *next = new int[n + 1];
    getnext(t, next);
    for (int i =0, j = -1; s[i]; i++) {
        while(j != -1 && s[i] - t[j + 1]) j = next[j];
        cout << j  << " " << s[i] << endl;
        if (s[i] == t[j + 1]) j += 1;
        if (t[j + 1] == 0) return i - n + 1;
    }
    delete[] next;
    return -1;
}

代码和求next数组非常相似,因为是应用的是同一个想法,这部分模拟一下就可以很容易理解


总结

不加注释的完整代码

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string.h>
using namespace std;

void getnext(const char *t, int *next) {
    next[0] = -1;
    int j = -1;
    for (int i = 1; t[i]; i++) {
        while(j != -1 && t[j + 1] != t[i]) j = next[j];
        if (t[j + 1] == t[i]) j += 1;
        next[i] = j;
    }
}

int kmp(const char *s, const char *t) {
    int n = strlen(t);
    int *next = new int[n + 1];
    getnext(t, next);
    for (int i =0, j = -1; s[i]; i++) {
        while(j != -1 && s[i] - t[j + 1]) j = next[j];
        cout << j  << " " << s[i] << endl;
        if (s[i] == t[j + 1]) j += 1;
        if (t[j + 1] == 0) return i - n + 1;
    }
    delete[] next;
    return -1;
}

int main() {

    char a[100], b[100];
    cin >> a >> b;
    cout << kmp(a, b) << endl;
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值