Python 实现 KMP 算法

Haystack :需要搜索给定模式的字符串。
:要搜索的模式。

时间复杂度 :搜索部分(strstr 方法)具有复杂度 O(n),其中 n 是 haystack 的长度但是针也被预先解析为构建前缀表 O(m) 是构建前缀表所必需的,其中 m 是长度针。
因此,KMP 的总时间复杂度为 O(n + m)
空间复杂度 : **O(m),**因为针上有前缀表。

注意:以下实现返回 haystack 中匹配的起始位置(如果匹配)else 返回 -1,对于边缘情况,例如,如果 needle / haystack 是空字符串或在 haystack 中找不到针。

def get_prefix_table(needle):
    prefix_set = set()
    n = len(needle)
    prefix_table = [0]*n
    delimeter = 1
    while(delimeter<n):
        prefix_set.add(needle[:delimeter])
        j = 1
        while(j<delimeter+1):
            if needle[j:delimeter+1] in prefix_set:
                prefix_table[delimeter] = delimeter - j + 1
                break
            j += 1
        delimeter += 1
    return prefix_table

def strstr(haystack, needle):
    # m: denoting the position within S where the prospective match for W begins
    # i: denoting the index of the currently considered character in W.
    haystack_len = len(haystack)
    needle_len = len(needle)
    if (needle_len > haystack_len) or (not haystack_len) or (not needle_len):
        return -1
    prefix_table = get_prefix_table(needle)
    m = i = 0
    while((i<needle_len) and (m<haystack_len)):
        if haystack[m] == needle[i]:
            i += 1
            m += 1
        else:
            if i != 0:
                i = prefix_table[i-1]
            else:
                m += 1
    if i==needle_len and haystack[m-1] == needle[i-1]:
        return m - needle_len
    else:
        return -1

if __name__ == '__main__':
    needle = 'abcaby'
    haystack = 'abxabcabcaby'
    print strstr(haystack, needle)