KMP算法详解

KMP算法详解

首先回忆一下我们的朴素式模式匹配,对于朴素式模式匹配算法,他是存在“回溯”的情况的,即发现匹配失败之后,上一次匹配的下一格开始重新匹配,可以发现,这样的算法时间复杂度很高,所以我们来看一下KMP算法

KMP算法相对于朴素式模式匹配算法最大的优点就是主串指针不回溯,只有模式串的指针回溯

下面我们来分析一下:

如果 j = k 时发现匹配失败,说明 1 ~ k - 1都匹配成功

KMP算法代码

int Index_KMP(string s, string T, int next[]){
	int i = 1, j = 1;
	while(i <= s.size() && j <= T.size()){
		if(j == 0 || s[i] == t[i]){
			++i;
			++j;
		}
		else
			j = next[j];
	}
	if(j > T.size())
		return i - T.size();
	else
		return 0;
}

上面代码中的next数组解释如下:当模式串的第j个字符匹配失败时,令模式跳到next[j]再继续匹配

求模式串的next数组

串的 前缀:包含第一个字符,且不包含最后一个字符的子串

串的后缀:包含最后一个字符,且不包含第一个字符的子串

当第j个字符匹配失败,由前1~j-1个字符组成的串记为S,则next[j] =S的最长相等前后缀长度+1

例如:模式串为 ‘ababaa’


序号j 1 2 3 4 5 6

模式串 a b a b a a

next[j] 0 1 1 2 3 4


再来一个做练习:‘aaaab’


序号j 1 2 3 4 5

模式串 a a a a b

next[j] 0 1 2 3 4


举例说明:比如说求next[3], 即在第三位匹配不对了 那么前面有aa是匹配上的,前缀是a ,后缀是a ,最长相同个数是1 最后再加1 得到next[3] = 2

下面写一下求模式串的next数组的代码

void get_next(string T, int next[]){
	int i = 1, j = 0;
	next[1] = 0;
	while(i < T.size()){
		if(j == 0 || T[i] == T[j]){
			++i;
			++j;
			next[i] = j;
		}
		else
			//否则令j = next[j];
	}
}
//KMP算法
int Index_KMP(string S,string T){
	int i = 1, j = 1;
	int next[T.size() + 1];
	get_next(T,next);//求模式串的next数组
	while(i <= S.size() && j <= T.size()){
		if(j == 0 || S[i] == T[i]){
			++i;
			++j;
		}
		else
			j = next[j];//模式串向右移动
	}
	if(j > T.size())
		return i - T.size();
	else
		return 0;
}

在上面的算法中,我们可以发现一些缺陷,比如说abbbabbc 与 abbc进行匹配,在发现第四个字母不同的时候,他会做一些无用功,

下面我们对KMP算法进一步进行优化,

利用nextval数组

nextval数组的求法:

先令nextval[1] = 0;
for(int j = 2; j < T.size();j++){
	if(T[NEXT[j]] == T[j])
		nextval[j] = nextval[next[j]];
	else
		nextval[j] = next[j];
}

KMP算法优化:当子串子串与模式串不匹配时j = nextval[j]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

允谦呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值