扩展KMP(占位)

先放代码。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N = 101010;
int next[N],extand[N];
void getnext(char *T){// next[i]: 以第i位置开始的子串 与 T的公共前缀 
     int i,length = strlen(T);
     next[0] = length;
     for(i=0;i<length-1&&T[i]==T[i+1];i++);
     next[1]=i;
     int a=1;
     for(int k = 2; k < length; k++){
          int p = a+next[a]-1, L = next[k-a];
          if( (k-1)+L >= p ){
              int j = (p-k+1)>0? (p-k+1) : 0; 
              while(k+j<length && T[k+j]==T[j]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较 
              next[k] = j, a = k;
          } 
          else next[k] = L;
    } 
}
void getextand(char *S,char *T){
    memset(next,0,sizeof(next)); 
    getnext(T); 
    int Slen = strlen(S), Tlen = strlen(T), a = 0;
    int MinLen = Slen>Tlen?Tlen:Slen;
    while(a<MinLen && S[a]==T[a]) a++;
    extand[0] = a, a = 0;
    for(int k = 1; k < Slen; k++){
        int p = a+extand[a]-1, L = next[k-a];  
        if( (k-1)+L >= p ){
            int j = (p-k+1)>0? (p-k+1) : 0; 
            while(k+j<Slen && j<Tlen && S[k+j]==T[j] ) j++; 
            extand[k] = j;a = k; 
        } 
        else extand[k] = L;         
    }
}

int main(){
    char s[N],t[N];
    while(~scanf("%s %s",s,t)){
        getextand(s,t); 
        for(int i = 0; i < strlen(t); i++)
            printf("%d ",next[i]);
        puts(""); 
        for(int i = 0; i < strlen(s); i++)
            printf("%d ",extand[i]);
        puts("");
    } 
    return 0;
}

下标从1开始。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N = 101010;
int next[N],extand[N];
char S[N],T[N];
void getnext(){// next[i]: 以第i位置开始的子串与T的公共前缀长度 
     int i,length=strlen(T+1);
     next[1]=length;
     for(i=0;i+1<length&&T[i+1]==T[i+2];i++);
     next[2]=i;
     int a=2;   //!
     for(int k=3;k<=length;k++){//长度+1,位置-1。 
          int p=a+next[a]-1, L=next[k-a+1];
          if(L>=p-k+1){
              int j=(p-k+1)>0?(p-k+1):0;//中断后可能是负的 
              while(k+j<=length&&T[k+j]==T[j+1]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较 
              next[k]=j, a=k;
          } 
          else next[k]=L;
    } 
}
void getextand(){
    memset(next,0,sizeof(next)); 
    getnext(); 
    int Slen=strlen(S+1),Tlen=strlen(T+1),a=0;
    int MinLen=Slen>Tlen?Tlen:Slen;
    while(a<MinLen&&S[a+1]==T[a+1]) a++;
    extand[1]=a, a=1;
    for(int k=2;k<=Slen;k++){
        int p=a+extand[a]-1,L=next[k-a+1];
        if(L>=p-k+1){
            int j=(p-k+1)>0?(p-k+1):0; 
            while(k+j<=Slen&&j<Tlen&&S[k+j]==T[j+1]) j++; 
            extand[k]=j;a=k; 
        }
        else extand[k]=L;    
    }
}

int main(){
    while(~scanf("%s %s",S+1,T+1)){
        getextand(); 
        for(int i=1;i<=strlen(T+1);i++)
            printf("%d ",next[i]);
        puts(""); 
        for(int i=1;i<=strlen(S+1);i++)
            printf("%d ",extand[i]);
        puts("");
    } 
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/hua-dong/p/8523320.html