KMP

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

next 数组

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

其中的值也可以认定为当我在当前位置匹配失败了,要回退的 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 数组一模一样。当匹配时,都向前,但当不匹配时,就向前回溯,找到最最适合的,看后一位时候匹配。

最后更新于