KMP算法

KMP算法

我们知道,KMP算法是用来匹配字符串的:有一个模式串(patter)ss(长的那个串),然后有一个待匹配串s, 然后我们要判断s 是否在ss中,KMP算法就高效解决这个问题。其中,最关键的就是求next[]数组了。

我们实质上是在找一个模式串(pattern)str0中的每个位置i 的nexti,前i子串内的最长的前缀与后缀,next[i]是这么定义的:【0,next[i]-1】的子串与【i-next[i],i-1】的子串相同,且使得next[i]最大;换言之,就是【0,i-1】子串的前缀与后缀相同的最大长度,即next[i]。当然,最符合next[]数组的原本解释,应该是这样的: 如果在i位置不匹配了,则在保证原串(长的那个)的 j位置不回溯的前提下,得到待匹配串的匹配起始位置next[i]。

在这里插入图片描述

void get_next(const string& s,int next[])
{
	 int i=0;     //扫描s时的位置 
	 int j=-1;    //前缀位置 
	 next[0] = -1;//开始时,没有前缀,没有后缀 
	 
	 while(i<s.length()){
		  if(j == -1||s[i] == s[j]){ 
			  //如果匹配成功,则继续向右移动,找下一个位置的最大的前缀与后缀相等 
			   j++;   //右移 
			   i++;   //右移 
			   next[i] = j; //记录该位置的长度 
			  }
	          //如果不匹配了,则缩短长度:在不移动i的前提下,移动j来进行新一轮匹配 
		  else j = next[j];
	 }
}

改进版

  • 上面的算法是有缺陷的,主要体现在下面例子中:
    -在这里插入图片描述

在这里插入图片描述

  • 会发现,这样移动是没有意义的,因为 C != B;应该直接移动到 -1位置,改进版算法其实很简单:
void get_nextval(const string& s,int next_val[])
{
    int i=0;
    int j=-1;
    next_val[0] = -1;
    while(i<s.length()){
   	  if(j == -1||s[i] == s[j]){
   		   j++;
   		   i++;
   		   if(s[i] == s[j]){                                
   		            next_val[i] = next_val[j];
   		   }
   		   else next_val[i] = j;
   		  }
   	 else j = next_val[j];
    }
}

相等的时候,就跳过,直接把next_val[i]回到前面去,这是因为,我们要回到next[i]最初定义中去,是说:不匹配时,移动回去,即当ss[k](这是匹配时,较长的那个串) != s[i]时,既然ss[k] != s[i],自然也不会等于s[j] ,所以往前移到next_val[i] = next_val[j]

发现KMP算法真是好难理解啊,真的想了很久,才搞懂,发现它的代码实现真的很神奇!神奇的KMP!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值