扩展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; }
It is your time to fight!