KMP算法笔记

61 阅读1分钟
void getNext(int* next, const string& s){
    int j = -1;
    next[0] = j;
    for(int i = 1; i < s.size(); i++) { // 注意i从1开始
        while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了
            j = next[j]; // 向前回退
        }
        if (s[i] == s[j + 1]) { // 找到相同的前后缀
            j++;
        }
        next[i] = j; // 将j(前缀的长度)赋给next[i]
    }
}

这是代码随想录给出的找最长公共子串的代码,当中跳过了一些细节的思考过程。(代码随想录 (programmercarl.com))

重点

  • next[j+1]表示字符串前j个字符的最长公共子串长度。
  • 进入for循环后,变量j的存在就类似于一个静态变量,在循环结束前(得到最终结果前)赋值始终不变,除非遇到改变它赋值的语句。
  • for循环内的while循环在亲后缀不同时起到类似递归的作用,不断地寻找前一个公共子串的长度,直到s[i]终于和s[j+1]相同,或变成-1。

一些问题

  • 为什么是j = next[j]?因为j始终表示前缀子串的的末尾,next[j]就是模式串前j个字符的最长公共子串的末尾。
  • 为什么最后是next[i]=j?因为next数组是每个数都减了1的,j实际上代表的就是公共前缀子串长。