KMP算法中的NEXT[ ] 数组手算方法(严蔚敏版本)

我们学习了没有改进的KMP算法后,可以知道通过NEXT[ ] 数组可以有效降低时间复杂度,将其从简单模式匹配的O(MN)降低为(M+N),那么,他是如何计算NEXT[ ] 的值呢?

我们假设有一串主串‘abaabb’,主串的指针为i,模式串的指针为j。那么我们可以知道,NEXT[ ] 中应该填入j,即NEXT[ j ]。在KMP算法中,通过学习得知,主串指针i是不会变小的。

这里介绍一种快速手算KMP算法中的NEXT[ ]数组手算方法:

假设主串为‘abaabb’,主串指针默认为i,模式串指针默认为j。我们使用的是严老师的数据结构所讲的,那么NEXT[ j ]数组起始是NEXT[ 1 ]=0(这是默认的),由此我们可以无脑写出NEXT[2]=1。

在KMP算法中,计算模式串abaabb的next数组(从1开始计数,且next[1] = 0)的过程如下:

  1. 初始化

    • 主串索引:1: a, 2: b, 3: a, 4: a, 5: b, 6: b

    • next[1] = 0,next[2] =1 。(无脑写)

    • next[]数组值为next[j+1],最大值也next[j+1],即如果当前位置(如在计算第10个索引时,第二个索引位置已经为next[2]了)最大next数组为next[2],那么下一个位置的(第11个索引位置)最大值只能为next[3]。可以小于等于3,不能超过3。

  2. 计算步骤(在计算过程中,计算第i个位置时,从第i-1个位置开始看,不看第i这个位置)

 根据当前需计算索引的前一个索引下next数组的值来计算。

分为前缀和后缀。

如:aba,已经知道我们需要计算‘aba’的next数组,已知‘ab’的next数组在‘b’这位置的值为1,那么我们这样画一个括号,即‘ab)a’,来计算‘)’后的a的next数组的值,这样方便看。相当于现在的前缀就是第一个‘a’,后缀为‘b’,因为‘ab’的next数组在‘b’这位置的值为1,所以只拿从前缀往后数的一个元素,即‘a’本身,同理,拿出后缀往前数的第一个元素,即‘b’本身。‘a’和‘b’不想等,所以当前索引值下的next数组值为0+1=1。
同理,‘abaab’的第二个‘b’的next数组值为2。计算如下:

在第二个b前画个括号,即‘abaa)b’,前缀为第一个‘a’,后缀为第三个‘a’,已经知道了第四个索引(第三个‘a’)位置的next数组的值为2,所以我们要匹配从前缀开始数的前两个元素,即'ab',同理,从后缀开始数两个元素'aa'(后缀是从后往前数,但是拿出来是从前往后拿,例如abcdef,从后缀开始数三个元素拿出来之后是‘dfe’!!!接下来匹配从前缀中取出来的两个元素和从后缀取出来的两个元素,很显然'aa'≠‘ab’,所以当前next数组的值减1,从2变为1,接下来从前缀开始往后数,取出一个元素,即前缀'a'(主串中索引为1的‘a’),同理,后缀也取出一个元素,即后缀‘a’(主串中索引为4的‘a’),很显然,‘a’=‘a’,那么此时的next数组的值就为1+1=2,所以在‘abaab’索引为5即第二个‘b’的位置的next数组的值为2。

最终next数组:next = [0, 1, 1, 2, 2, 3] (索引从1到6)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值