KMP通俗易懂(python)

~~ 今天学了KMP算法,课上怎么也想不通,就花了一个晚自习去单步代码,最后终于明白了,下面我来分享一下我的总结,若有什么问题,欢迎各位大佬指正!

我按照我的思路叙述:首先我们来看下这个字符串mum_str = 'abcdabcd',规定它有一个这样的列表 mum_list[-1, 0, 0, 0, 0, 1, 2, 3]

这个list 怎么来的呢?首先把这个字符串最后一个字符拿出来提到最前面,变成了mum_str = 'dabcdabc',再来一个有len(mum_str)个元素的列表,第一个元素固定为-1,从mum_str[1]开始,在这个例子中从'a'开始,如果前面有‘a’(不算num_str[0]显然没有),就在mum_list[1]的位置写上0
接下来是‘b’,前面没有‘b’吧?没有就在mum_list[2]的位置写上0。后面的‘c’,‘d’不用解释了吧?

但是

mum_str[5]开始就不一样,这个位置的‘a’在前面出现过吗?有就在mum_list[5]这个位置上写1,

注意!注意!注意!

下一个是问mum_str[6]的‘b’前面出现过吗?错!
因为之前的mum_list[5]这个位置上写了1(不为0)。
所以,这时应该问‘ab’在前面出现过吗?
,就在mum_list[6]的位置写2;
没有,再问mum_str[6]的‘b’前面出现过吗?
之后就是问‘abc’在前面出现过吗?
,就在mum_list[7]的位置写3。
没有,就…
以此类推

下面是代码,自己验证一下

def get_pnext(p):
    """
    :param p:mum_str
    :return: pnext
    """
    i, k, m = 0, -1, len(p)
    pnext = [-1] * m
    while i < m - 1:
        if k == -1 or p[i] == p[k]:
            i, k = i + 1, k + 1
            pnext[i] = k
        else:
            k = pnext[k]
    return pnext
mum_str = 'abcdabcd'
pnext = get_pnext(mum_str)
print(pnext)

当然这个想法是根据结果的出来的,至少你接受了这个,看一遍母串,就能写出这个pnext。

KMP的难点就在这个pnext上,解决了这个,KMP有手就行

下面是KMP的完整代码

# KMP算法与朴素匹配不同的是,母串的索引不回退

def matching_KMP(t, p, pnext):
    """

    :param t: mum_str
    :param p: son_str
    :param pnext: get next position
    :return: 子串在母串的位置,没找到返回-1
    """
    j, i = 0, 0  # j为母串的索引,i为子串的索引
    n, m = len(t), len(p)
    while j < n and i < m:# i=m说明找到了匹配
        if i == -1 or t[j] == p[i]:
            j, i = j + 1, i + 1
        else:
            i = pnext[i]  # 这里是关键之处,下面会说明怎么得到pnext[i]
    if i == m:  # 找到了
        return j - i  # 因为子串长度为i,所以需要键去i
    else:
        return -1  # 没找到,返回-1


def get_pnext(p):
    """
    :param p:mum_str
    :return: pnext
    """
    i, k, m = 0, -1, len(p)
    pnext = [-1] * m
    while i < m - 1:
        if k == -1 or p[i] == p[k]:
            i, k = i + 1, k + 1
            pnext[i] = k
        else:
            k = pnext[k]
    return pnext


if __name__ == '__main__':
    mum_str = 'dabcdabcd'
    son_str = 'abcd'
    pnext = get_pnext(mum_str)
    ans = matching_KMP(mum_str, son_str, pnext)
    print(ans)
    print(pnext)

暂时就先说明到这,没有什么比自己敲一遍代码更有效的掌握!(?)
学习算法和数据结构,还任重而道远嘞…

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值