“KMP算法”中如何获取next[]数组

“KMP算法”中如何获取next[]数组:

以模式串T=“abaabcac”为例:

一、应对考试(要求写出T对应的next[]数组):(快速手算)

首先列出T的所有前缀(本身不是):

前缀最大匹配数
a0
ab0
aba1
abaa1
abaab2
abaabc0
abaabca1
Ta b a a b c a c
-1 0 0 1 1 2 0 1
next[]0 1 1 2 2 3 1 2

过程:首先得到各个前缀的最大匹配数(0,0,1,1,2,0,1);然后在前面填个-1->(-1,0,0,1,1,2,0,1);next[]=(-1,0,0,1,1,2,0,1)+(1,1,1,1,1,1,1,1) = ( 0 1 1 2 2 3 1 2)

解释:例如如果在abaabc的最后一个c失配了,我们知道c前面的子串abaab的最大匹配数为2(匹配串为:ab);所以往后移动几位才能找到应该与主串失配位重新比较的位置呢?

我们知道往后移动2+1(失配位前面的子串的最大匹配数+1)个单位时,能满足要求。

二、适合写代码的方法:

(一)法只适合手算,代码不好实现
(二)法:
假设next[0]第一位闲置,用0填补,方便后续操作;
首先规定:next[1] = 0; next[2] = 1; (这是一定正确的)
当 i >.3时:假设在模式串的第 i 位置失配,如何计算next[i]呢?

令j = next[i-1]
首先比较 T[ j ] 和 T[ i-1 ] 是否相等,如果相等:next[ i ] = j +1;
如果不等:更新 j = next[ j ];
继续判断 T[ j ] 和 T[ i-1 ]是否相等。。。

如果 j =0 了,表示比较到了模式串的第一个字母了,所以此时:next[ i ] = 1;

填完 next[]数组 即结束。。。。。

Python实现:


def get_next(T):
    global next
    next = [0 for k in range(len(T))]
    #  当len(T) == 1 or 2 or 3 时,next数组为默认值
    if len(T)==1:                  # 注意:len(T)=len(模式串)+1
        return next
    if len(T)==2:
        next[1] = 0
        return next
    if len(T)==3:
        next[1], next[2] = 0, 1
        return next

    #  当len(T)>3时:
    if len(T)>3:
        next[1], next[2] = 0, 1
        i = 3
        j = next[i - 1]           # 计算next[i]前对j的初始化
        while i <= (len(T)-1):
            if j == 0:
                next[i] = 1
                i += 1
                j = next[i - 1]
                continue
            if T[i - 1] == T[j]:      # T[i-1]为失配位置i的前一个位置的字母
                next[i] = j + 1
                i += 1
                j = next[i - 1]     # 计算next[i]前对j的初始化
            else:
                # 不满足相等的条件,则更新 j
                j = next[j]
        return next
    pass
def main():
    line = "abaabcac"
    T = [0]+list(line)       # 数组首位空置不用,用0填充
    print(T)

    next = get_next(T)      # 获取next数组
    print(next)
    pass
main()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值