【KMP】优质模板推荐+解读

KMP – y神模板

引言:由于本人与4月20日前周五的一节数据结构课中偶然听到了老师讲kmp这个算法的概念并且发现老师讲的听不懂一点儿导致异常难受,于是花了两天左右自行弄懂了kmp算法的逻辑,并写下本文以便以后复习,并作留念。

声明:本文仅供对kmp理解的人扩展思路,不能教会不会kmp算法的人kmp的理解核心 Σ(っ °Д °;)っ

还不会kmp?:以下学习资料(教程链接)助你速通,

  1. 大神左程云细说kmp
  2. kmp简单讲解动画
  3. 民间讲解教程
  4. AcWing算法基础课–第二单元内容(需要付费)

题目练习

一、next数组快速生成

#include <iostream>

using namespace std;

const int N = 1e5+1, M = 1e6+1;
char s[M], p[N];
int n, m, ne[N];

int main() {
    cin >> n >> p+1 >> m >> s+1;
    // 创建next数组代码:
    for (int i = 2, j = 0; i <= n; i ++) {
        while (j && p[i] != p[j+1]) j = ne[j];
        if (p[i] == p[j+1]) j ++;
        ne[i] = j;
    }
    // kmp匹配代码:
   /*
   		暂时省略
   */
    return 0;
}

前置条件的解释

对于代码中的变量名,这里进行解释:

变量名 含义
s 主串
p 模式串(需要在主串中被匹配并找到位置)
n 模式串长度
m 主串长度
i 当前需要求的next数组下标位置
j i位置字符回溯后的位置

对于本模板需要注意两个小的细节:

  1. 输出输出的字符下标都是从1开始存储,0位置置空
  2. 每次比对时都是比对s串的i下标和p串的j+1位下标
  3. 回溯:也是kmp和暴力匹配的本质区别,在于匹配失败,instead of i向后移动,but j 向前移动我称之为"回溯",注意和递归那个回溯本质不是同一个东西。

如图所示:

在这里插入图片描述

对于模式串ababab在字符数组中的存储情况如上。

代码图示解读

for循环

对于代码:

for (int i = 2, j = 0; i <= n; i ++)

ij的默认位置如图所示:
在这里插入图片描述

解释:

细节 对应的原理
i=2 i=1位置的相等前后缀最大长度一定是0
next数组中默认都为0
所以i直接跳过第一位即可
j=0 每一次都比较j+1i位置是否相等,
最开始也就是第一次迭代需要求1位置next数组的值,
那么就需要比较j=1i=2位置在模式串p中字符是否相等
i<=n 这个简单,越过n就超过模式串p的长度了,同时也就表明next数组计算完毕。
for循环中后半部分代码(比较简单放在前面)
if (p[i] == p[j+1]) j ++;
ne[i] = j;

这段代码的含义:如果i位置字符和j+1位置字符相等,j后移一位,并且计算出了nexti位置的值。

如图:

在这里插入图片描述

for循环中第一句
while (j && p[i] != p[j+1]) j = ne[j];

如果不相等,使用ne(变量名冲突所以不适用next)数组回退。

二、kmp匹配部分

#include <iostream>

using namespace std;

const int N = 1e5+1, M = 1e6+1;
char s[M], p[N];
int n, m, ne[N];

int main() {
    cin >> n >> p+1 >> m >> s+1;
    // create nextArray.
    for (int i = 2, j = 0; i <= n; i ++) {
        while (j && p[i] != p[j+1]) j = ne[j];
        if (p[i] == p[j+1]) j ++;
        ne[i] = j;
    }
    // kmp.
    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 - n << ' ';
            j = ne[j];
        }
    }
    return 0;
}

每次进行匹配,

  • 如果匹配成功j++

  • 如果匹配不成功,并且j还有向前回溯的可能,则回溯j = ne[j]

  • 如果已经匹配出一个结果,j == n,打印这个子串的初始位置,并且向前回溯

相关推荐

  1. 7-17 KMP模式匹配算法

    2024-04-21 08:54:03       22 阅读
  2. P5410 【模板】扩展 KMP/exKMP(Z 函数)

    2024-04-21 08:54:03       52 阅读
  3. 模型推理--KV cache解读

    2024-04-21 08:54:03       41 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-21 08:54:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-21 08:54:03       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-21 08:54:03       82 阅读
  4. Python语言-面向对象

    2024-04-21 08:54:03       91 阅读

热门阅读

  1. 游程编码(Run-Length Encoding, RLE)的python实现

    2024-04-21 08:54:03       24 阅读
  2. 吉林教育报社投稿信箱投稿邮箱

    2024-04-21 08:54:03       28 阅读
  3. 面试 Python 基础八股文十问十答第二期

    2024-04-21 08:54:03       40 阅读
  4. 前端开发中可以使用的 ChatGPT Prompts

    2024-04-21 08:54:03       37 阅读
  5. nodejs(项目架构MVC,IOC,DI)

    2024-04-21 08:54:03       37 阅读
  6. 深入探讨负载均衡的原理及算法

    2024-04-21 08:54:03       40 阅读
  7. Linux多媒体基础 - v4l2 vb2_queue的用法

    2024-04-21 08:54:03       31 阅读
  8. 线段树、树状数组、归并排序模板

    2024-04-21 08:54:03       35 阅读
  9. VSCode下的开发与编译

    2024-04-21 08:54:03       37 阅读
  10. 【设计模式】外观模式

    2024-04-21 08:54:03       29 阅读