KMP算法

KMP算法的应用。记WORD的长度为m,TEXT的长度为n, 暴力法的时间复杂度为O(nm), KMP算法可将复杂度降至O(n+m).

KMP算法的总体思想是让遍历TEXT的指针不回溯,从而保证关于n的线性复杂度。

为了实现TEXT指针j不回溯这一点,则只能要求WORD指针i回溯。现在问题在于,每次WORD[i]与TEXT[j]匹配失败后,i应该回溯到哪里呢?答案是回溯到k处,k等于字符串WORD[0:(j-1)]公共前缀后缀的最大长度。例如,字符串”aba”对应的最大公共前缀后缀是”a”, 字符串”abaab”对应的最大公共前缀后缀是”ab”,字符串”aaaa”对应的最大公共前缀后缀是”aaa”(注意前缀和后缀不能是字符串本身)。由于后缀WORD[(j-k):(j-1)] == TEXT[(i-k):(i-1)],则前缀WORD[0:(k-1)] == TEXT[(i-k):(i-1)],接下来只要继续比较WORD[k]与TEXT[i]是否相同即可。

将WORD数组的最大公共前缀后缀信息保存在数组next中,next[j]表示WORD[0:(j-1)]的最大共同前缀后缀长,并定义next[0] = -1表示当WORD的第一个字符与TEXT[i]不匹配时需要TEXT指针i后移。从而KMP算法的程序分为两个部分,一部分计算next数组,另一部分遍历TEXT数组计算匹配个数。


int kmp()

{

	int cnt = 0, i = 0, j = 0, word_len = strlen(word);

	while (j < strlen(text))

	{

		if (i == -1 || word[i] == text[j])

		{

			i++;

			j++;

		}

		else

		{

			i = next[i];

		}

		if (i == word_len)

		{

			cnt ++;

			i = next[i];

		}

	}

	return cnt;

}

该部分复杂度为O(n),因为两次执行j++之间每次执行i = next[i]的次数不会超过上次j++连续执行的次数,因此while循环的执行次数上界为两倍的j++执行次数,即2n.

计算next数组

void cal_next()			// 计算word字符串的最大共同前缀后缀长数组, next[i]: word[0:i-1]的最大共同前缀后缀长
{
	next[0] = -1;
	int i = -1, j = 0;
	while (j < strlen(word))
	{
		if (i == -1 || word[i] == word[j])
		{
			next[++j] = ++i;
		}
		else
		{
			i = next[i];
		}
	}
}

去B站上听了印度程序员讲的kmp算法,听了两遍懂了,果然对于算法这种东西,还是有一个好例子跟详细的流程更容易懂啊

书上写的都是什么狗屁东西,看了半天都尼玛没看懂,根本没流程。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

deebcjrb

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

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

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

打赏作者

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

抵扣说明:

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

余额充值