KMP算法next数组推导

来源:互联网 发布:电商大数据分析平台 编辑:程序博客网 时间:2024/06/03 21:29

来一段KMP算法的代码

#include <iostream>using namespace std;void nextVal(char * s, int * next);int main(){    char * mainStr = "abcabeabcabcabxfdabdsabcabcab";    char * childStr = "abcab";    int * next = new int[strlen(childStr) + 1];    nextVal(childStr, next);    int ans = 0;    int i = 0;    int j = 0;    while (mainStr[i] != '\0')    {        if (j == -1 || mainStr[i] == childStr[j])        {            ++j;            ++i;            if (childStr[j] == '\0')            {                ++ans;                j = next[j];            }        }        else        {            j = next[j];        }    }    cout << ans;    delete[] next;    cin.get();}//next数组的推导void nextVal(char * s, int * next){    int i = 0, j = -1;    next[0] = -1;    while (s[i] != '\0')    {        if (j == -1 || s[j] == s[i])        {            ++i;            ++j;            next[i] = j;        }        else        {            j = next[j];         //标注[1],这里是个难点        }    }}

标注[1]的一个问题:

问:为什么如果下标为i 与下表为j 的元素不等时,j要重新赋值为next[j] ?

答:

其实推导next数组的过程中,也是一个子串与主串匹配的过程

当后缀下标为i 的字符 与 前缀下标为j 的字符不匹配时:
j 被赋值为next[j],既子串中如果第j 个字符不匹配,则应该将j 变为j 所对应的next数组里的值

如果未匹配的j 前面的子串前后缀没有相似的,则j 的next数组的值为0
如果未匹配的j 前面的子串前后缀有相似的,则j 的next数组的值将不是0。这里不好理解,举个例子:假如未匹配的j 前面的串为:abcab,其中前后缀有相似:ab,那么j 不匹配时,j的值将变为next数组的值,而next数组的值为c所对应的下标——因为ab与ab相同,在j为匹配之前,j前面的串的后缀的ab已经匹配,所以前缀的ab就不需要再判断,已经知道那是匹配的了,这样也就省去了大量不必要的j 与i 的回溯

*这篇主要讨论标注[1]处的问题,没有具体说明如何推导next,只是写了代码。有空补充一下具体步骤 :P

0 0
原创粉丝点击