KMP算法总结

KMP算法关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。

KMP算法的关键在于求算next[]数组的值,即求算A串的最长后缀与B串的前缀相同的长度,具体如下:

1. 令k代表B串开头所在的序号,j代表A串开头所在的序号,起始的时候j=1,k=0。

2. 我们比较一下B前串和A后串是否相等。首先比较A[j]==B[k],如果相等,那么next[j+1]=k+1,然后j++,k++。

关键就是理解这个next[j+1]=k+1,简单说就是A串中的第j+1个字符的next函数值由他前面的字符与B前串相等的个数来决定,就是说A串中的第j+1个字符的next函数值,是由他前面的字符串决定的。

3. 当A[j]!=B[k],即不相等的时侯,那么j不动,k返回到开头(因该是next[k]位置,便于理解先假设是返回k=0处),即从头比较B[0]与A[j],B[1]与A[j+1].

例如:第 j+1 个字符的next函数值next[j+1]等于3,意味着 它的前三个字符串,A[j-2]A[j-1]A[j]==B[0]B[1]B[2].

求next数组:

void Next(char str[], int len) {
    nex[0] = -1;
    int i = 0, j = -1;
    while (i < len) {
        if (~j && str[i] != str[j])
            j = nex[j];
        else nex[++i] = ++j;
    }
}

KMP匹配:

int KMP(char sa[], char sb[], int la, int lb) {
    Next(sb, lb);
    int i = 0, j = 0;
    while (i < la) {
        if (~j && sa[i] != sb[j])
            j = nex[j];
        else i++, j++;
    }
    return j;
}

例题:https://blog.csdn.net/lzyws739307453/article/details/97889297