根据算法导论实现KMP算法(python 3)

在我看来阮一峰的字符串匹配的KMP算法 对于入门挺好,但是对于KMP的实现很不友好,被绕进去了很多次.
始终觉得<算法导论>里面的方法更加简洁一点,虽然需要自己花点时间演算一下才能理解.

#计算next数组
def compute_prefix(p):
    m = len(p)
    res = [-1 for _ in range(m)]#置-1作为没有找到匹配前缀的标志
    res[0] = -1
    k = -1
    for q in range(1,m):
        while k > -1 and p[k+1]!=p[q]:
            k = res[k]#若失位,在已匹配到的信息中找.(若得到-1,会跳出循环)
        if p[k+1] == p[q]:
            k = k + 1
        res[q] = k
    return res

#KMP匹配过程
def kmp_matcher(t,p):
    n, m = len(t), len(p)
    nxt = compute_prefix(p)#得到next数组
    q = -1
    for i in range(n):
        #若失位的操作
        while q > -1 and p[q+1] != t[i]:
            q = nxt[q]
        #从失位恢复处或p最左端继续匹配
        if p[q+1] == t[i]:
            q = q + 1
        #当p字符串的下标q达到m-1时,意味着匹配成功,找到一个目标pattern
        if q == (m - 1):
            #输出pattern起始位置
            print("Pattern occurs with shift ",i-m+1)
            #继续在t中寻找下一个pattern
            q = nxt[q]
#测试
p = "ababababca"
# t中藏了两个ababababca
t = "vhjvgdhacvjchacvajcbcababababcahvcdakcacbcbajhcacvacgacahcjachascababababca"
kmp_matcher(t,p)
Pattern occurs with shift  21
Pattern occurs with shift  65

在电话面试里遇到了KMP算法, 算是之前看过也了解过, 但是没有仔细去真正实现过,或许KMP本身不太适合作为电话面试的题目,也或许是自己的表达能力还未到水平,脑里对KMP的概念难以用语言表达出(最长公共前后缀? 实现O(m+n)? next数组? 似乎几个关键词都难以表达对KMP的理解)
网上对KMP的现实有很多,但是在我看来,在计算next数组的部分应该要达到O(m)级别的,看了一下很多人的做法都是用python set集合或者遍历以一个O(m*m)作为解决方案,是不够准确的. 对于KMP的细究还是有必要的, 如果不细究早就用朴素匹配解决了, 哪里还用得着设计一个KMP.
另一个要点是入门一个算法,第一步是抽象想象,能以一个动画想象算法过程.第二步是以一个实例用纸笔演算一次. 加上最后的实现,基本可以掌握一个算法的70%了.
附上一张截图帮助理解next数组的计算.
KMP_next

猜你喜欢

转载自blog.csdn.net/m0_37422289/article/details/80497677