kmp算法记录

最长公共前后缀学习:https://www.shpity.com/index.php/archives/262/

参考资料:https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/

https://iq.opengenus.org/prefix-table-lps/

# kmp, 旋转词
pattern = 'ABCDABD'
target = '12345'+'12345'

def longest_prefix_suffix(pattern):
    # 求解最长公共前后缀
    lps = [0]*len(pattern)
    i, length = 1, 0     # length:前缀符的最后一个索引,i:后缀符的最后一个索引,不断向后探索
    while i < len(pattern):    # 在模式串长度内
        print(f"i:{i}, length:{length}")
        if pattern[length] == pattern[i]:    # 在模式串中前缀最后一个字符和后缀的最后一个字符相等,说明有可移动空间,length+1
            length += 1
            lps[i] = length
            i += 1
        else:
            if length != 0:
                length = lps[length-1]       # 回退到前一个区间去查找
            else:
                lps[i] = 0    # length=0, lps归位, 目标更新到下一索引
                i += 1
        print(f"pattern:{pattern}, lps:{lps}\n")
    return lps
lps = longest_prefix_suffix(pattern)
print("lps", lps)

M, N = len(pattern), len(target)
i, j = 0, 0
while (N - i) >= (M - j):
    if target[i] == pattern[j]:   # 模式串和目标串匹配了,i+1, j+1
        i += 1
        j += 1
    if j == M:     # j=M, 完全匹配,回退到前一大公共前后缀,继续往后匹配
        print(f"find the pattern at index: {str(i-j)}, {target[i-j:]}")
        j = lps[j-1]
    # mismatch after j matches,i在索引范围内且位置j和位置i的字符没有匹配,进入该逻辑
    elif i < N and pattern[j] != target[i]:
        if j != 0:
            j = lps[j-1]
        else:
            i += 1

 

posted @ 2022-08-12 20:11  今夜无风  阅读(15)  评论(0编辑  收藏  举报