KMP算法

#include<iostream>
#include<cstring>
using namespace std;

const int MAXN = 10010;
int next[MAXN];

//getNext求解长度为len的字符串s的next数组 
void getNext(char s[], int len){
	int j = -1;
	next[0] = -1;	//初始化j = next[0] = -1 
	for(int i = 1; i < len; i++){	//求解next[1] ~ next[len -1] 
		while(j != -1 && s[i] != s[j + 1]){
			j = next[j];	//反复令j = next[j] 
		}	//直到j回退到-1,或是s[i] == s[j + 1] 
		if(s[i] == s[j + 1]){	//如果s[i] == s[j + 1] 
			j++;	//则next[i] = j + 1,先令j指向这个位置 
		}
		next[i] = j;	//令next[i] = j 
	}
}

//优化后的next数组,getNextval求解长度为len的字符串s的nextval数组 
void getNextval(char s[], int len){
	int j = -1;
	next[0] = -1;	//初始化j = nextval[0] = -1 
	for(int i = 1; i < len; i++){	//求解nextval[1] ~ nextval[len -1] 
		while(j != -1 && s[i] != s[j + 1]){
			j = nextval[j];	//反复令j = nextval[j] 
		}	//直到j回退到-1,或是s[i] == s[j + 1] 
		if(s[i] == s[j + 1]){	//如果s[i] == s[j + 1] 
			j++;	//令j指向原next[i]的位置 
		}
		//与getNext函数相比只有下面不同 
		if(j == -1 || s[i + 1] != s[j + 1]){	//j == -1不需要回退 
			nextval[i] = j;	//getNext函数中只有这句 
		} else {
			nextval[i] = nextval[j];
		} 
	}
}

//KMP算法,判断pattern是否是text的子串
bool KMP(char text[], char pattern[]){
	int n = strlen(text), m = strlen(pattern);	//字符串长度 
	getNext(pattern, m);	//计算pattern的next数组 
	int j = -1;	//初始化j为-1,表示当前还没有任意一位被匹配 
	for(int i = 0; i < n; i++){	//试图匹配text[i] 
		while(j != -1 && text[i] != pattern[j + 1]){
			j = next[j];	//不断回退,直到j回到-1或text[i]==pattern[j+1] 
		}
		if(text[i] == pattern[j + 1]){
			j++;	//text[i]与patten[j+1]匹配成功,令j加1 
		}
		if(j == m - 1){	//patten完全匹配,说明pattern是text的子串 
			return true;
		}
	}
	return false;	//执行完text还没匹配成功,说明pattern不是text的子串 
}

//KMP算法,统计pattern在text中出现的次数 
int KMP_(char text[], char pattern[]){
	int n = strlen(text), m = strlen(pattern);	//字符串长度 
	getNext(pattern, m);	//计算pattern的next数组 
	int ans = 0, j = -1;	//ans表示成功匹配次数,并初始化j为-1 
	for(int i = 0; i < n; i++){	//试图匹配text[i] 
		while(j != -1 && text[i] != pattern[j + 1]){
			j = next[j];	//不断回退,直到j回到-1或text[i]==pattern[j+1] 
		}
		if(text[i] == pattern[j + 1]){
			j++;	//text[i]与pattern[j+1]匹配成功,令j加1 
		}
		if(j == m - 1){	//pattern完全匹配,说明pattern是text的子串 
			ans++;	//成功匹配次数加1 
			j = next[j];	//让j回退到next[j]继续匹配 
		}
	}
	return ans;	//返回成功匹配次数 
}

int main(){
	char text[MAXN], pattern[MAXN];
	scanf("%s%s", text, pattern);
	printf("%d\n", KMP(text, pattern));
	printf("%d\n", KMP_(text, pattern));
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值