【KMP】从原理上详解next数组和nextval数组

本文将从原理上详细解释KMP算法中的next数组以及nextval数组,尽量让大家明白它们到底在记录什么,为什么要这样算。以及现在普遍的KMP算法实现当中的next数组与前两者有何不同。篇幅较长,但尽量讲清楚。

next数组

next数组到底在记录什么?

虽然数据结构中对next数组有定义,但并不易于理解,因此我个人对next数组进行了一个简单解释:

next数组指示了当前模式串在该位置匹配冲突(即失配,个人习惯称冲突)时,应该将模式串的哪一位与此位对齐。

这里为刚学习KMP的朋友解释一下,KMP算法进行字符串匹配时,被检索的串称为“文本串”,要检索的目标串称为“模式串”。next数组与nextval数组的求解只与模式串有关。

举个例子
假设需要在字符串 “abaabbcabaabcac” 中查找是否存在字符串 “abaabcac”,那么 "abaabbcabaabcac"就是文本串,"abaabcac"就是模式串。

这里其它的许多详解中会直接告诉你,next数组的第一位是0,第二位是1,然后从第三位开始继续算什么的,但很少看到有解释为什么第一位一定是0,第二位一定是1

为了解释这个问题,我们首先要搞清楚模式串的“位”是什么样的。
对“abaabcac”来说,第一个字符a就是第一位,不要受一些编程语言思维的影响认为这是第0位。

位数 1 2 3 4 5 6 7 8
模式串 a b a a b c a c

但是为了便于理解,我们假想模式串的最前面还有一个空白字符位,称为第0位,即:

位数 0 1 2 3 4 5 6 7 8
模式串 a b a a b c a c

现在,我们再来对照前面给出的定义:
next数组指示了当前模式串在该位置匹配冲突时,应该将模式串的哪一位与此位对齐。

是不是就理解为什么第一位一定是0,第二位一定是1了?
还没有?那我们再假想一个文本串加上来。

待求位:      1  2  3  4  5  6  7  8
文本串:      x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x
模式串:      a  b  a  a  b  c  a  c

现在标红的位置发生冲突,那么下一步应该让模式串的哪一位跟当前冲突的 x 位对齐呢?没错,就是第0位。也就是变成:

待求位:      1  2  3  4  5  6  7  8
文本串:      x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x
模式串:          a  b  a  a  b  c  a  c
位数:          0  1  2  3  4  5  6  7  8

所以,当模式串的第一位发生冲突时,应该将模式串的第0位与当前位置对齐,也就是next[1]=0;


继续看第二位发生冲突的情况:

待求位:      1  2  3  4  5  6  7  8
文本串:      a  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x
模式串:      a  b  a  a  b  c  a  c

此时需要将模式串移动为:

待求位:      1  2  3  4  5  6  7  8
文本串:      a  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x
模式串:          a  b  a  a  b  c  a  c
位数:          0  1  2  3  4  5  6  7  8

所以,当模式串的第二位发生冲突时,应该将模式串的第1位与当前位置对齐,也就是next[2]=1;

无论模式串如何变化,只要其长度大于等于2,这两种情况都是固定的,因此next[1]一定为0,next[2]一定为1。


继续看第三位发生冲突的情况:

待求位:      1  2  3  4  5  6  7  8
文本串:      a  b  x  x  x  x  x  x  x  x  x  x  x  x  x  x
模式串:      a  b  a  a  b  c  a  c

这时,假如我们仍然只移

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值