KMP算法理解

KMP算法的理解着实花了不少时间,幸好网上前辈的博客写得都相当好,结合几篇博客仔细想想还是可以理解的,这里仅做一下整理。

KMP算法概念理解看这篇博客就够了字符串匹配的KMP算法by阮一峰
主要的逻辑那篇博客都有讲,求出next数组,进行简单的加减即可完成匹配。至于求解next数组,则是KMP算法的关键也是难点所在。
需参考以下两篇博客:
1、http://www.cnblogs.com/c-cloud/p/3224788.html
2、http://www.cnblogs.com/10jschen/archive/2012/08/21/2648451.html

第一篇的博主提出的求对称性的思想非常利于理解,逻辑上证明了next数组用于匹配字符串的可行性。

第二篇博主要介绍了next数组的求解算法以及配图,特此摘录一下重点部分。

代码实现

1 void makeNext(const char P[],int next[])
 2 {
 3     int q,k;//q:模版字符串下标;k:最大前后缀长度
 4     int m = strlen(P);//模版字符串长度
 5     next[0] = 0;//模版字符串的第一个字符的最大前后缀长度为0
 6     for (q = 1,k = 0; q < m; ++q)//for循环,从第二个字符开始,依次计算每一个字符对应的next值
 7     {
 8         while(k > 0 && P[q] != P[k])//递归的求出P[0]···P[q]的最大的相同的前后缀长度k
 9             k = next[k-1];          //不理解没关系看下面的分析,这个while循环是整段代码的精髓所在,确实不好理解 
10         if (P[q] == P[k])//如果相等,那么最大相同前后缀长度加1
11         {
12             k++;
13         }
14         next[q] = k;
15     }
16} 

对于其中的while循环:
  1、已知前一步计算时最大相同的前后缀长度为k(k>0),即P[0]···P[k-1];
  2、此时比较第k项P[k]与P[q],如图1所示
  3、如果P[K]等于P[q],那么很简单跳出while循环;
  4、关键!关键有木有!关键如果不等呢???那么我们应该利用已经得到的next[0]···next[k-1]来求P[0]···P[k-1]这个子串中最大相同前后缀,可能有同学要问了——为什么要求P[0]···P[k-1]的最大相同前后缀呢???是啊!为什么呢? 原因在于P[k]已经和P[q]失配了,而且P[q-k] ··· P[q-1]又与P[0] ···P[k-1]相同,看来P[0]···P[k-1]这么长的子串是用不了了,那么我要找个同样也是P[0]打头、P[k-1]结尾的子串即P[0]···Pj-1,看看它的下一项P[j]是否能和P[q]匹配。如图2所示
30163843-2fd01a5b306b4fbb8183b0a7c145d79c.png30171002-e67282f4d1d84cb59e0152826b58e6ac.png

其中的图2便是理解while循环中k = next[k-1];这一步的关键。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值