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)