KMP算法详解C

本文介绍了KMP算法,一种优化的字符串匹配算法,相较于BF算法,KMP通过next数组避免了不必要的回溯,提高了效率。详细阐述了next数组的生成及其优化,包括nextval数组的计算,以提高字符串搜索的性能。通过实例展示了KMP算法的实现过程。
摘要由CSDN通过智能技术生成

引入KMP:字符串寻找字串,并返回字串起始下标位置

关于这个问题,我的另外一篇博客有一个初步认识

BF算法简单了解C(含图)
https://blog.csdn.net/sakeww/article/details/122985104

只不过这个方法太过“暴力”,时间复杂度太大
而KMP算法可以优化以下使其更加快速

了解KMP:

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n) [1] 。 来自-------百度百科。

KMP和BF区别:

KMP 和 BF 唯一不一样的地方在,我主串的 i 并不会回退,并且 j 也不会移动到 0 号位置

探究:

在这里插入图片描述
在这里插入图片描述

引入next数组

KMP 的精髓就是 next 数组:也就是用 next[j] = k;来表示,不同的 j 来对应一个 K 值, 这个 K 就是你将来要移动的 j要移动的位置。

而 K 的值是这样求的:
1、规则:找到匹配成功部分的两个相等的真子串(不包含本身),一个以下标 0 字符开始,另一个以 j-1 下标字符结尾。
2、不管什么数据 next[0] = -1;next[1] = 0;在这里,我们以下标来开始,而说到的第几个第几个是从 1 开始;

根据规则我们可以写出next的具体值:
在这里插入图片描述
在这里插入图片描述

根据这个上面的两个具体数组我们可以发现一些规律:
1.next第零位置我们设为-1,
2.每个数字都和它的前一个位置有关
a.比上一个位置多一
b.直接是零或者1

总结规律,用数学表示:
设字符串为:p
在这里插入图片描述

代码:

void GetNext(int* next, const char* sub)
{
	int lensub = strlen(sub);
	next[0] = -1;
	next[1] = 0;
	int i = 2;//下一项
	int k = 0;//前一项的K
	while (i < lensub)//next数组还没有遍历完
	{
		if ((k == -1) || sub[k] == sub[i - 1])//
		{
			next[i] = k + 1;
			i++;
			k++;//k = k+1???//下一个K的值新的K值
		}
		else
		{
			k = next[k];
		}
	}
}

int KMP(const char* s, const char* sub, int pos)
{
	int i = pos;
	int j = 0;
	int lens = strlen(s);
	int lensub = strlen(sub);
	int* next = (int*)malloc(lensub * sizeof(int));//和子串一样长
	assert(next != NULL);
	GetNext(next, sub);
	while (i < lens && j < lensub)
	{
		if ((j == -1) || (s[i] == sub[j]))
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];
		}
	}
	free(next);
	if (j >= lensub)
	{
		return i - j;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char* str = "ababcabcdabcde";
	char* sub = "abcd";
	printf("%d\n", KMP(str, sub, 0));
	return 0;
}

next数组优化:

next 数组的优化,即如何得到 nextval 数组:有如下串: aaaaaaaab,他的 next 数组是-1,0,1,2,3,4,5,6,7.

而修正后的数组 nextval 是:-1, -1, -1, -1, -1, -1, -1, -1, 7。
为什么出现修正后的数组,假设在 5 号处失败了,那退一步还是a,还是相等,接着退还是 a

例题:
t=‘abcaabbcabcaabdab’
该模式串的 next 数组的值为( 0 1 1 1 2 2 3 1 1 2 3 4 5 6 7 1 2) ,
nextval 数组的值为 (0 1 1 0 2 1 3 1 0 1 1 0 2 1 7 0 1)
在这里插入图片描述
用我们的做法是这样的:
KMP讲解不一样,只需要我们这个每一项加一即可

nextval 求法:
如果当前回退的位置,正好是和当前字符一样,那么就写那个字符的nextval值
不一样就写自己的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值