KMP:在主串S中找子串T的位置KMP算法的时间复杂度O(|S|+|T|)。
#define maxn 1000 char s[maxn],t[maxn];//s为主串,t为子串 int net[maxn],l1,l2;//l1为主串长度,l2为子串长度 void get_next() { int i=0,j=-1; net[0]=-1; while(i<l2) { if (j==-1 ||t[i]==t[j]) { ++i,++j; if (t[i]!=t[j]) net[i]=j; //优化next数组 else net[i]=net[j]; } else j=net[j]; } /*for (i=0;i<l2;i++) printf("next[%d]=%d ",i,next[i]); */ } //返回子串在主串第pos个字符之后的位置 //若不存在则返回0 int KMP(int pos) { int i=pos,j=0; get_next(); //核心部分 while(i<l1&&j<l2) { if (j==-1||s[i]==t[j]) i++,j++; else j=net[j]; } if (j==l2) return i-l2; else return 0; }
void getNext() { Next[1] = 0; for (int i = 2, j = 0; i <= n; i++) { while(j > 0 && a[i] != a[j+1]) j = Next[j]; if (a[i] == a[j+1]) j++; Next[i] = j; } } void KMP() { for (int i = 1, j = 0; i <= m; i++) { while(j > 0 && (j == n || b[i] != a[j+1])) j = Next[j]; if (b[i] == a[j+1]) j++; f[i] = j; // if (f[i] == n) 此时是A在B中的某一次出现 } }
扩展KMP:
给定串S,和串T,设S的长度为n,T的长度为m,求T与S的每一个后缀(包括S)的最长公共前缀。复杂度为O(n+m)。
设extend数组,extend[i]表示T与S[i,n-1]的最长公共前缀,要求出所有extend[i](0<=i<n)。
注意到,如果有一个位置extend[i]=m,则表示T在S中出现,而且是在位置i出现,这就是标准的KMP问题,所以说拓展kmp是对KMP算法的扩展,所以一般将它称为扩展KMP算法。
详细过程参考博客: https://blog.csdn.net/qq_40160605/article/details/80407554
https://blog.csdn.net/dyx404514/article/details/41831947
const int K=1000005; int nt[K],extand[K]; char S[K]; void Getnext(char *T,int *next) { int len=strlen(T),a=0; next[0]=len; while(a<len-1 && T[a]==T[a+1]) a++; next[1]=a; a=1; for(int k=2; k<len; 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<len && T[k+j]==T[j]) j++; next[k]=j; a=k; } else next[k]=L; } } void GetExtand(char *S,char *T,int *next) { Getnext(T,next); int slen=strlen(S),tlen=strlen(T),a=0; int MinLen = slen < tlen ? slen : tlen; 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() { while(scanf("%s%s",S,T)==2) { GetExtand(S,T,nt); for(int i=0; i<strlen(T); i++) printf("%d ",nt[i]); puts(""); for(int i=0; i<strlen(S); i++) printf("%d ",extand[i]); puts(""); } return 0; }