图解 朴素匹配,KMP算法 next数组 nextval数组求解 及代码实现

本文详细介绍了朴素匹配算法及其时间复杂度问题,然后转向KMP算法,解释了如何利用部分匹配值优化匹配过程。通过示例说明了next数组的计算过程,以及如何使用nextval数组进行匹配。附带了C语言实现的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

朴素匹配

朴素匹配又称暴力匹配,其时间复杂度为O(m*n)

缺点:时间复杂度高

 

例如:在ABEECDEEF中查找是否有子串EEF

1.

ABEECDEEF

EEF

将A于E匹配发现不相同,子串回到起点,主串后移一位

2.

ABEECDEEF

EEF

B与E匹配发现不相同,子串回到起点,主串后移一位

3.

ABEECDEEF

EEF

E与E匹配成功,子串和主串都后移一位,继续匹配

4.

ABEECDEEF

EEF

此时,E与E匹配相同,子串和主串都后移一位,继续匹配

5.

ABEECDEEF

EEF

此时F与C匹配不相同 ,子串回到起点,主串回到第一个匹配上的字符的下一个位置(回到第二个E)

6.

ABEECDEEF

EEF

继续匹配,直至遇到第一个匹配上的字符

......

7.

ABEECDEEF

EEF

E与E匹配相同,子串和主串都后移一位,继续匹配

8.

ABEECDEEF

EEF

E与E匹配相同,子串和主串都后移一位,继续匹配

9.

ABEECDEEF

EEF

F与F匹配相同此时子串已匹配完,匹配完成

 

代码如下:

#include<stdio.h>
#include<assert.h>
#include<string.h>
int BF(const char *str,const char *sub,int pos)
{
	assert(str != NULL && sub != NULL);
	int i = pos;
	int j = 0;
	int lens = strlen(str);
	int lensub = strlen(sub);

	while(j < lensub && i < lens)
	{
		if(str[i] == sub[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i-j+1;
			j = 0;
		}
	}
	if(j >= lensub)
	{
		return i-j
### KMP算法next数组的计算方法 在KMP算法中,`next`数组用于记录模式串的部分匹配值,即前缀和后缀的最大重合部分长度。通过构建这个数组可以有效地减少不必要的比较次数。 #### `i` 和 `j` 指针的作用 变量`i`作为遍历模式串的位置索引,而`j`则是追踪当前已知最大公共前后缀位置的指针。初始状态下设置`next[0]=-1`是为了处理特殊情况下的回溯逻辑[^1]。 ```cpp int i = 0, j = -1; next[0] = -1; ``` 当遇到字符匹配成功时(`p[i]==p[j]`),两个指针都向前移动一位并更新对应的`next`值;如果发生失配,则依据之前存储的信息调整`j`指向更早的一个可能匹配点继续尝试: ```cpp if (j == -1 || p[i] == p[j]) { ++i; ++j; next[i] = j; } else { j = next[j]; } ``` 这段代码实现了动态规划的思想,在每一步决策过程中充分利用已有信息来指导下一步操作,从而提高了效率[^2]。 #### 完整版C++实现 以下是完整的C++版本的`getNext()`函数实现,该函数接收一个字符串参数`p`以及一个整型数组`next`作为输出结果保存处: ```cpp void getNext(const string& p, int* next) { int i = 0, j = -1; next[0] = -1; while (i < static_cast<int>(p.size()) - 1) { if (j == -1 || p[i] == p[j]) { ++i; ++j; next[i] = j; // 当前位置的next等于上一个位置加一后的j值 } else { j = next[j]; // 不匹配的情况下利用历史数据进行跳转优化 } } } ``` 此段程序能够正确地计算出给定模式串对应的所有`next`数值,并将其存入传入的数组中供后续使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值