扩展KMP的next数组求的是子字符串的每一个位置!!和KMP算法的next数组有所区别

即子字符串的每一个位置和子字符串的第一个位置的最长前缀

代码:

void getnext(char s[],int len)
{
    int i=0,j,pos;
    next[0] = len;
    while(s[i] == s[i+1] && i+1 < len)
        i++;
    next[1] = i;
    pos = 1;
    for(i=2;i<len;i++){
        if(next[i-pos]+i < next[pos]+pos)
            next[i] = next[i-pos];
        else{
            j=next[pos]+pos-i;
            if(j<0)j=0;
            while(i+j < len && s[j] == s[j+i])
                j++;
            next[i]=j;
            pos = i;
        }
    }
}
//1231231234
//10 0 0 6 0 0 3 0 0 0

扩展KMP实现,其实相当于写了俩遍的getnext

#include <bits/stdc++.h>
using namespace std;
const int maxx = 10010;
int next[maxx],ans[maxx];
void getnext(char s[],int len)
{
    int i=0,j,pos=1;
    next[0] = len;
    while(s[i] == s[i+1] && i+1 < len)
        i++;
    next[1] = i;
    for(i=2;i<len;i++){
        if(next[i-pos]+i < next[pos]+pos)
            next[i] = next[i-pos];
        else{
            j=next[pos]+pos-i;
            if(j<0)j=0;
            while(i+j < len && s[j] == s[j+i])
                j++;
            next[i]=j;
            pos = i;
        }
    }
}

void exkmp(char s1[],int l1,char s2[],int l2)
{
    int i=0,j,pos=0;
    getnext(s2,l2);
    while(s1[i] == s2[i] && i<l2 && i<l1)
        i++;
    ans[0] = i;
    for(i=1;i<l1;i++){
        if(next[i-pos]+i < ans[pos] + pos)
            ans[i] = next[i-pos];
        else{
            j=ans[pos]+pos-i;
            if(j<0)j=0;
            while(i+j<l1&&j<l2&&s1[j+i]==s2[j])
                j++;
            ans[i]=j;
            pos=i;
        }
    }
}
char s1[maxx],s2[maxx];
int main(){
    scanf("%s",s1);
    scanf("%s",s2);
    int l1 = strlen(s1),l2 = strlen(s2);
    exkmp(s1,l1,s2,l2);
    for(int i=0;i<l1;i++){
        cout<<ans[i]<<" ";
    }
    return 0;
}