🐋
Blog
算法
算法
  • 算法
  • 基础
    • 高精度
    • 二分
    • 位运算
    • 贪心
    • KMP
    • Master Theorem
    • 前缀和 & 差分
    • sort
    • 双指
  • 数据结构
    • 数据结构模拟
  • 数学
    • 组合数
    • 约数
    • 欧拉函数
    • 扩展欧几里得
    • 高斯消元
    • 容斥原理
    • 线性筛
    • 快速幂
  • 动态规划
    • 背包
    • 字符串匹配
    • 区间DP
  • 图论
    • BFS
    • DFS
由 GitBook 提供支持
在本页
  • next 数组
  • 模式匹配
  1. 基础

KMP

学习 KMP 算法最好还是先背模板,写个几遍之后就理解的差不多了。

next 数组

next 数组可以认定为一个状态转移数组,其含义是最大前缀和后缀的相同的值的数量。这个解释不够清晰。举个例子:

a b a a b c a ca\ b\ a\ a\ b\ c\ a\ ca b a a b c a c
0 0 1 1 2 0 1 00\ 0\ 1\ 1\ 2\ 0\ 1\ 00 0 1 1 2 0 1 0

其中的值也可以认定为当我在当前位置匹配失败了,要回退的 index - 1。那么我在前面加个空格,就是正常的回退 index。

那么如何求 next 数组?

先看一下代码。

for (int i = 2, j = 0; i <= m; i ++) {
    while (j && p[i] != p[j + 1]) j = ne[j];
    if (p[i] == p[j + 1]) j ++;
    ne[i] = j;
}

求解 next 数组类似于双指加回溯。i 指针一直递增,j 指针指向的前面的字符和 i 指针前面的部分字符相同。当二者指向的字符相同时,二者都增加,但当不同时,j 需要回溯向前找到最长的那个字符,看它的下一位是否和 i 指向的字符是否相同,不同再回溯。回溯的过程,由于一直都是再找最大的那个,所以是最优解。

模式匹配

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];
    }
}

求解出 next 数组就简单了,模式匹配的思路和求解 next 数组一模一样。当匹配时,都向前,但当不匹配时,就向前回溯,找到最最适合的,看后一位时候匹配。

上一页贪心下一页Master Theorem

最后更新于2年前