kmp入门理解(多种求next数组样例详解)

我看到的大神的从入门到深刻理解链接比我讲述的更为透彻
原文:https://blog.csdn.net/v_july_v/article/details/7041827
下面是我的对于kmp见解
kmp含义:
在我看来kmp说简单点就是求在母串中子串出现的位置;解题的关键就在于就求子串的相同的前缀和后缀用next数组存储在第i个字符(包含第i个字符)前有多少个相同的字符(下面讲述求法),另一个就是在kmp函数中找出那个位置的下标;
其实还有一种就是暴力求出下标的方法,暴力法求解由于对时间度要求很高所以,在题目要求子串,和母串长度很大时此方法明显就不适合了
AC如下 :

  int Violentsearch(char* s, char* p)
 {
 	int sLen = strlen(s);
 	int pLen = strlen(p);

 	int i = 0;
 	int j = 0;
 	while (i < sLen && j < pLen)
 	{
 		if (s[i] == p[j])
 		{
 			//如果当前字符匹配成功(即S[i] == P[j]),则i++,j++    
 			i++;
 			j++;
 		}
 		else
 		{
 			//如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0    
 			i = i - j + 1;
 			//如果失配,每一次都要从上一次母串最开始遍历的下一个字符开始重新遍历
 			//例如母串是aabcy子串是abcy遍历到第二个失配那么第二次就母串应该从第
 			//二个字符a开始重新遍历
 			j = 0;
 		}
 	}
 	//匹配成功,返回模式串p在文本串s中的位置,否则返回-1
 	if (j == pLen)
 		return i - j;
 	else
 		return -1;}

kmp数组next求法:
next数组的作用就是在kmp函数中子串和母串比较时不相等的话把子串前移到子串前面一部分和母串有相同的的地方例如

在这里插入图片描述

在这里插入图片描述
对于子串p:a b c d a b c y
对应的next数组应该是 0 0 0 0 1 2 3 0
初始化时数组全为零
定义一个i=1; j=0; j在a的位置,i在b的位置,不相等所以i++;j还不动,直到i在第五个字符a的时候出现第一个相等的此时i++;j++;next[i]=j;后面的同样相等直到遇到y的时候此时j在d上不相等所以j=next[j-1](j前面又没有相等的前缀和后缀)
建议使用第二种第一种容易出现错误
第一种:

void get_next()
{
	int i = 1, j = 0;
	while(i < lenb)
	{
		if(j == 0 && b[i] != b[j])
		{
			i ++;
			next[i] = 0;
		}
		else if(j > 0 && b[i] != b[j])
			j = next[j-1];
		else
		{
			next[i] = j+1;
			i ++;
			j ++;
		}
	}
}

第二种

 void Get_next()
 {
 	int i=1,j=0;
 	next[0]=-1;
 	while(i<m)
 	{
 		if(j==-1||p[i]==p[j])
 		{
 			j++;
 			i++;
 			next[i]=j;//当前i的位置有j个相等的字符
 		}
 		else
 		{
 			j=next[j];//缩小前缀
 		}
 	}
 }

对于kmp函数:
先看看代码吧

  {
      Get_next();
  	int i=0,j=0;
  	while(i<n)
  	{
  	//要是子串和母串相同继续往后进行比较
  		if(j==-1||s[i]==p[j])
  		{
  			i++;
  			j++;   
  		}
  		else//不相等就把子串往后移到子串前面的几个字符和目前母串前几个相同的地方
  		      //也就是上面的两张图片
  		{
  			j=next[j];
  		}
  		
  	}
  	if(i==m)
  	return i-j;
  	else
  	return -1;
  }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

皮皮皮皮皮皮皮卡乒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值