讲解参考:https://www.jianshu.com/p/107e47994d49

要点总结:


(1)目的:母串S,len(S)=n,子串T, len(T)=m, 两个字符串存储时下标都从0开始,suffix(i)表示S串中从下标i开始的后缀,扩展kmp算法可以求每个suffix(i)和T的最长公共前缀长度

(2)nxt[i]表示T串的suffix(i)和T串的最长公共前缀长度

(3)Extend[i]表示S串的suffix(i)和T串的最长公共前缀长度

(4)nxt数组和Extend数组的求法相同,在求nxt时,T串既充当S串又充当T串

(5)求nxt[]时要预处理出nxt[0]和nxt[1],求Extend[]时,因为nxt数组已经求出,所以只需预处理出Extend[0]即可

 

模版:


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000010; //字符串长度最大值
int nxt[maxn],Extend[maxn];
char s1[maxn],s2[maxn];
//预处理计算nxt数组
void getnxt(char str[])
{
    int i=0,j,po,len=strlen(str);
    nxt[0]=len; //初始化nxt[0]
    while(str[i]==str[i+1] && i+1<len) i++; nxt[1]=i; //计算nxt[1]
    po=1; //初始化po的位置
    for(i=2;i<len;i++)
    {
        if(nxt[i-po]+i < nxt[po]+po) //第一种情况,可以直接得到nxt[i]的值
            nxt[i]=nxt[i-po];
        else //第二种情况,要继续匹配才能得到nxt[i]的值
        {
            j = nxt[po]+po-i;
            if(j<0) j=0; //如果i>po+nxt[po],则要从头开始匹配
            while(i+j<len && str[j]==str[j+i]) j++; nxt[i]=j;
            po=i; //更新po的位置
        }
    }
}

//计算Extendend数组
void EXKMP(char s1[],char s2[])
{
    int i=0,j,po,len=strlen(s1),l2=strlen(s2);
    getnxt(s2); //计算子串的nxt数组
    while(s1[i]==s2[i] && i<l2 && i<len) i++; Extend[0]=i;
    po=0; //初始化po的位置x
    for(i=1;i<len;i++)
    {
        if(nxt[i-po]+i < Extend[po]+po) //第一种情况,直接可以得到Extendend[i]的值
            Extend[i]=nxt[i-po];
        else //第二种情况,要继续匹配才能得到Extendend[i]的值
        {
            j = Extend[po]+po-i;
            if(j<0) j=0; //如果i>Extendend[po]+po则要从头开始匹配
            while(i+j<len && j<l2 && s1[j+i]==s2[j]) j++; Extend[i]=j;
            po=i; //更新po的位置
        }
    }
}
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    scanf("%s", s1);
    scanf("%s", s2);//s2是子串
    EXKMP(s1,s2);
    int len = strlen(s1);
    for(int i = 0; i < len; i++)
        printf("suffix(%d):%s  和子串的最长公共前缀长度为:%d\n",i, s1+i, Extend[i]);
    return 0;
}

测试样例:第二个字符串为子串

aabaaaab
aaabc

 输出:

suffix(0):aabaaaab  和子串的最长公共前缀长度为:2
suffix(1):abaaaab  和子串的最长公共前缀长度为:1
suffix(2):baaaab  和子串的最长公共前缀长度为:0
suffix(3):aaaab  和子串的最长公共前缀长度为:3
suffix(4):aaab  和子串的最长公共前缀长度为:4
suffix(5):aab  和子串的最长公共前缀长度为:2
suffix(6):ab  和子串的最长公共前缀长度为:1
suffix(7):b  和子串的最长公共前缀长度为:0