根据牛客网左神讲的内容改编而成。KMP算法通过最长前后缀实现了加速,可以通过反证法加以证明,有兴趣的可以参考算法导论。

判断pattern在Text的什么位置出现的

#include<cstdio>
#include<cstring>
int next[100];
int ans=0;
void getNext(char s[], int len){  //此处的next数组存的是i-1前不含本身的最长前后缀长度 
	next[0] = -1; //人为规定 
	next[1] = 0; //人为规定 
	int i = 2;
	int cn = 0; //跳的位置
	while(i < len){
		if(s[i-1] == s[cn]){
			next[i++]=++cn;
		}else if(cn > 0){
			cn=next[cn];
		}else{
			next[i++]=0;
		}
	} 
}
 
 
int KMP(char text[], char pattern[]){
	int n = strlen(text);
	int m = strlen(pattern);
	getNext(pattern, m);
	int i=0,j=0;
	while(i <n && j <m){
		if(text[i] == pattern[j]){
			i++;
			j++;
		}else if(next[j] == -1){ //pattern串已经滑到头了 
			i++;
		}else{
			j = next[j];    //继续滑动至最大前缀 
		}		
	}
	return j==m?(i-j):-1; // 找到则返回找到的位置,找不到返回-1 
}

int main(){
	char text[]="habahwriteababacidufd";
	char pattern[]="ababac";
	int x =KMP(text,pattern);
	printf("%d",x);
	return 0;
} 

统计模式串Pattern在匹配串Text中出现的次数

#include<cstdio>
#include<cstring>
int next[100];
void getNext(char s[], int len){  //此处的next数组存的是i-1前不含本身的最长前后缀长度 
	next[0] = -1; //人为规定 
	next[1] = 0; //人为规定 
	int i = 2;
	int cn = 0; //跳的位置
	while(i < len){
		if(s[i-1] == s[cn]){
			next[i++]=++cn;
		}else if(cn > 0){
			cn=next[cn];
		}else{
			next[i++]=0;
		}
	} 
}
 
 
int KMP(char text[], char pattern[]){
	int n = strlen(text);
	int m = strlen(pattern);
	int ans = 0;
	getNext(pattern, m);
	int i=0,j=0;
	while(i <n && j <m){
		if(text[i] == pattern[j]){
			i++;
			j++;
		}else if(next[j] == -1){ //pattern串已经滑到头了 
			i++;
		}else{
			j = next[j];    //继续滑动至最大前缀 
		}
		if(j==m){
			j=next[j-1];
			ans++;
		}		
	}
	return ans;
}

int main(){
	char text[]="habahwriteababacidufd";
	char pattern[]="aba";
	int x =KMP(text,pattern);
	printf("%d",x);
	return 0;
}