KMP算法(快速手算求模式串的next),超详细KMP的子串匹配流程并用伪代码实现KMP算法

KMP算法

一.了解KMP算法

1.什么是kmp算法

KMP算法是一种字符串匹配算法,用于在一个文本串中查找一个模式串的出现位置。它通过预处理模式串,利用已知信息来避免在文本串中不必要的回溯,从而提高匹配效率。具体来说,KMP算法使用一个部分匹配表(即next数组)来记录模式串中每个前缀子串的最长公共前后缀长度,然后根据这个表进行匹配。时间复杂度为O(m+n),其中m和n分别为模式串和文本串的长度。

二.利用KMP算法快速求模式串的next值(手算法)

假设此处的模式串为"abaac"
在这里插入图片描述
在这里插入图片描述

1.串的前缀和后缀

串的前缀: 包括第一个字符不包括最后一个字符的字串
串的后缀: 包括最后一个字符不包括第一个字符的字串
当模式串在第1~n个开始与主串不匹配时,此时的next值为最长相等前缀和后缀长度+1
(但是匹配的前缀后缀的最大长度必须小于匹配失败字符之前模式字符串的长度)

比如:模式字符串为acaa他在第四个字符与主串匹配失败
则前缀和后缀的长度必须小于3,首先我们可以以前后缀长度大到小依次判断前后缀是否相等,显然这里的最大前缀长度是2前缀为ac,后缀为ca,前后缀不相等,开始找前后缀长度为1的,前缀为a后缀为a,前后缀相等,则模式字串的第四个字符与主串不匹配时,它的next为1+1=2

1.模式串与主串的第一个就不匹配时,主串向后移动一位,模式串不动,则此时的next为0
2.模式串与主串的第二个不匹配时,此时与主串不匹配的字符之前的字串长度为1,不存在前缀和后缀,所以此时的next等于0+1
3…模式串与主串的第三个不匹配时,此时与主串不匹配的字符之前的字串长度为2,前缀为a 后缀为c,前后缀不相等,则next等于0+1
4.模式串与主串的第四个不匹配时,此时与主串不匹配的字符之前的字串长度为3,最大前后缀长度为2,前缀为ab,后缀为ba吗,前后缀不相等,开始找前后缀长度为1时的情况,前缀为a后缀为a,前后缀相等,则此时的next值为1+1
其他的也是按照此方法即可推出所有的next值

三.利用KMP算法快速求模式串的next值(伪代码实现)

在这里插入图片描述

get_next(char ch[],int next[],int length)//length是模式串ch的长度
{
    
    
	int j = 0;//模式串里面元素对应的next值
	int i = 1;//指的是模式串元素的位序,也是next数组的索引
	next[1]=0;//模式串第一个元素next值为1
	while(i<length)
	{
    
    
		if(j==0 || ch[j]==ch[i])//
		{
    
    
			next[++i]=++j;
		}
		else
		{
    
    
		//上面条件不成立时j=1  ,得到j = next[j] = next[1] =0
			j = next[j];//如果前缀后缀不相等让j初始化为0,进行下一次循环,从而让下一个字串的next等于上一个字串的next对应的值
		}
	}
}

四.KMP算法匹配流程

在这里插入图片描述
i 指的是模式串元素的位序,也是next数组的索引
j 模式串里面元素对应的next值
第一躺匹配
i =1 j=1
next[] = {0,1,1,2,1}

	a		b		a		c		a		c		a		b		a
	||		!=
	a		c		a		b		a

第二趟匹配
i = 2 j = next[1]=0

	a		b		a		c		a		c		a		b		a
			!=
			a		c		a		b		a

第三趟匹配(这里的最大相等的前缀后缀长度为1,将模式串)
i=3 j =1

a		b		a		c		a		c		a		b		a
				||		||		||		!=
	 			a		c		a		b		a

i = 5;j=3
第四趟匹配
i = 6 ,j =next[4] =2

a		b		a		c		a		c		a		b		a
								||		||		||		||		||
	 							a		c		a		b		a

五.KMP找子串伪代码实现

int KMP_index(char main_str[],char substring[],int next[],int length_main,int int length_substring,)
{
    
    //main_str是主串 substring是模式串(子串),next是模式串的next值组成的数组,length_main主串长度,length_substring子串长度
	int  i= 1;
	int j = 1;
	while(i<=length_main && j<= length_substring)
	{
    
    
		if(j==0	|| main_str[i] == substring[j])
		{
    
    
			++i;
			++j;
		}
		else
		{
    
    
			j = next[j];
		}
	}
	if{
    
    j>length_substring)
	{
    
    
		return i-length_substring;
	}
	else
		return 0;
}

六.总结

KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。其核心思想是利用已经匹配过的信息,尽量减少无效的比较次数。

具体实现步骤如下:

预处理模式串substring,得到一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从substring[next[i]]开始。

在主串mian_str中,从左往右逐个字符进行匹配。如果当前字符匹配成功,则继续匹配下一个字符;否则根据next数组移动模式串substring,直到可以继续匹配或者substring移到了最左端。

如果匹配成功,返回当前位置;否则继续在main_str中向右移动,重复上述过程。

KMP算法的时间复杂度为O(n+m),其中n和m分别为主串main_str和模式串substring的长度。由于预处理next数组的时间复杂度为O(m),因此KMP算法适用于模式串固定、多次匹配的情况。

猜你喜欢

转载自blog.csdn.net/qq_63713328/article/details/129712246
今日推荐