KMP算法 next函数 代码解析

KMP算法很早就接触了,记得自己看着代码也能理解实现,但是时间已久总是忘了如何编码,也许是自己对于next函数的理解一直停留在记忆层面上。

现在把KMP的next函数拿出来,看看能不能分析出一个门道,理解了它的逻辑,方式,才会记得比较熟悉吧。

KMP的思想这里不探讨了,直接上next函数的代码来分析。


void next(const char *T, int next[])
{
       int j = 0, k = -1;//两个位置指针,j表示当前匹配指针。
	   //j,k都代表了当前重复子串后的位置。即图(1)的F和D位置
       next[0] = -1;
	   //把第一个的位置置为-1,表示从头开始匹配
       while ( T[j] != '\0' )//while循环
       {
              if (k == -1 || T[j] == T[k])
              {
                     ++j; ++k;
                     if (T[j]!=T[k])
                            next[j] = k;
                     else
                            next[j] = next[k];
              }
              else
                     k = next[k];
       }
}


个人理解,这个next函数有两个目的,1.求一个最长重复序列;2.根据最长序列求回溯位置。

1.最长重复子序列:

比如ABCDABC,这个序列的最长重复字序列式ABC,当然,这里的最长重复要满足要求,前一个顶头,后一个顶着尾巴。如下图(1)所示。
CABCDABC,这个序列ABC子序列不满足前一个顶头的要求,所以这个序列的最长公共子序列是C。

2.回溯位置。如图一,F之前的最长子序列求出来以后,我们目的是计算F的回溯位置。按照理解,我们匹配失败后,可以让F回溯到D的位置,因为它们的前缀是相同的。

程序里还加了一个判断条件,就是继续还要判断F与D是否相等,如果相等,即都为F,那么F失败的时候回溯回来也是错误的,那么我们就然F指向D之前的位置。


图(1)




于是我们知道了程序的两个步骤,1,求最长子序列;2,求有效回溯位置(注意是有效);图(3)是程序的一个流程图:



图(2)


接下来,自己总结下next函数的思想。

next是一种DP的思想,即动态规划。next和k指针都记录了以前计算的结果,next为前面元素匹配位置,k记录当前最长字串,用于后面的计算。其实我们也可以写一个简单寻找最长重复序列的非DP算法,不过那会很费时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值