next数组_KMP算法next数组求解

KMP算法与BF算法的比较:

BF算法的想法十分朴素,即先将子串T的第一位与主串S的第一位对齐开始匹配,当不能匹配时将子串整体往后移一位,然后重新匹配,以此类推直至排出结果;如当遇到下图所示情况时,需将子串整体后移一位,将i,j分别回溯到主串第2位和子串第一位。

bd7f32996bea2d8fb1dd76586c52c2a1.png

KMP算法:

对BF进行思考后,我们会发现其实i可以不用回溯,只需要回溯j就可以完成匹配,因为我们完全可以只移动j来匹配所有的过程,例如下图时,我们可以不移动i,只将j移动到子串第三位;

223503e00dc0be8e17b7c79fdeda4d79.png

但是如果是让我们自己来匹配的话,我们肯定不会这么蠢,我们肯定不会把j移动到第三位,而是把j移动到第一位,为什么呢?我们自己也说不上来,这只是我们主观的巧合吗?再如下图,当我们遇到这种情况时也不会把j移到子串第三位,而是依然把j移到子串第1位,

fdaa7a446414f441803a85d741321969.png

为什么呢?因为我们知道子串第一位是A,而主串已经和子串匹配契合的部分中只有第一位是A,也就是说子串中j以前的部分中只有一个A,;再如下图所示情况,我们会将j移动到子串第二位来进行匹配,为什么?似乎是因为j之前的子串部分中有两个A;

c6e58a23864d4ced8a8cfbc236472ed0.png

从上面3个例子我们可以看出j的移动是有技巧的,那我们不妨设当i与j不匹配时,j应移到子串的下一个位置为k;我们动用一下逆向思维,再来看下图,如果两个矩形框起来的两个串是一样的,那么

f7743daf61783a76e5786053104b7440.png

对于第一个矩形框中的串有什么要求,是不是要求自己的后2两位与自己的前两位是相同的,那么相应的,如果一个串的后n位与自己的前n位相同,再在后面跟上一些未知的数是不是有可能在后一个矩形框里可能产生与前一个矩形框一样的串;好,现在我们再看下面的例子:

6b4e2e1645e54213aedcb14f662e3652.png

这时,i与j不匹配了,我们是不是应该将j移动到子串第二位,那么规律出来了,假如下次j应移动到子串的k位置,那么应满足:串T[0]—T[k-1]应与串T[j-k]—T[j-1]相同;

a23ccdffe2a839059813f2689485b7e0.png

那么大概清楚了k具有什么作用和性质,而next数组就是存下一个个k的值,比如next[3]的含义就是指当i=j=3时不匹配了,j下一步应移动到子串的k位置的k的值,那么假如我们可以求出next数组,那么是不是就可以在i与j不匹配时就直接把j移动到next[j]而避免掉无用的移法。那么怎么求next数组,求next数组其实就是求一个个k值;

首先当j==0时:此时应当将i往后移动一位,j不动,那么我们任意记一个-1作为k值来和其他只移动j的k值进行区分;

当j==1时:此时j肯定移动到0位置,那么next[1]=0;

当j==2时:那么就要看T[0]与T[1]是否相同,如果相同,则next[2]=1;否则next[2]=0;

当j==n时:那么所求的k就是满足j前面k位与子串前k位相同即T[0~k-1]==T[j-k~n-1],而反观next[n-1],(令m=next[n-1])其含义表示T[0~m-1]==T[j-m~n-2],那么会发现当T[n]==T[k]时,next[n]=m+1;假如不相等,那么第k位还有可能与主串i位相匹配,与判断第n-1位时类似,即next[n]=next[m]+1;

那么,到现在,我们已经可以求出next数组了,next数组是只与子串本身的前后相似性相关的数组,求解出来后可以得到i与j不匹配时j应移动至的最有效的位置,可以大幅减少j的移动次数,提高效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值