KMP演算法python實現

2021-09-17 08:55:05 字數 3283 閱讀 3752

目錄

一、找出prefix_table

二、kmp演算法實現

二、測試:

三、結果: 

四、時間複雜度簡單匹配演算法的時間複雜度為o(m*n),kmp匹配演算法時間複雜度為o(m+n).。

1、把要匹配的字串pattern拆成子串找出最大公共前字尾,原來的要匹配的字串列入為求最大公共前字尾的行列裡面。最大公共前字尾是指前後兩個子串相同,而且子串的長度最大,例如子串ababcaba的最大公共前字尾是aba。計算出當前的最大公共前字尾的長度作為prefix_table的元素。前面加上-1,完全不匹配的時候把整個子串移動後一位,就相當於移動到-1的位置。

第3個子串abab的最大公共前字尾是ab,下乙個子串只要判斷下乙個元素是不是a即可,假如是a,最大公共前字尾的長度+1,否則最大公共前字尾的長度-1,即此時要對比的物件是a,看看結尾的元素是不是a,是則把元素假如prefixtable。

def get_prefixtable(pattern):

"""通過傳入要和text匹配的子字串pattern,把pattern拆分成長度為1~len-1子串,

分別找出子串的最大前字尾的長度組成prefix_table

:param pattern:要匹配的子字串

:return:prefix列表

"""prefix = [none] * len(pattern)

prefix[0] = 0 #第乙個元素只有乙個元素,沒有前字尾所以為0

length = 0 # 最大前字尾的長度

i = 1 # 從第二個元素開始匹配

while i < len(pattern):

if pattern[i] == pattern[length]:

length += 1

# prefix[i] = length

# i += 1

else:

# 主要是針對開頭的元素,一直都匹配不到,

# 當最大前字尾減到1時就會在開頭元素不斷迴圈,此時讓他等於prefix[length - 1]即可

if length > 0:

length = prefix[length - 1]

# else:

# 記得一定要繼續移動i指標

prefix[i] = length

i += 1

return [-1] + prefix

pattern元素和text元素對相同則繼續移動指標,假如不相同則查詢prefixtable的值,該值對應的pattern元素是否相等,相等則繼續匹配,否則重複上面操作,若是遇到-1的情況,則讓i,j指標往後移動。
1、c和a不匹配,把子串整體往後移動,相當於對齊下標為-1的位置。

2、指標右移一位,abab都匹配上了,但是此時c不匹配,prefixtable顯示2,把下標為2的地方對準當前指標位置,繼續匹配,

此時匹配到字串,返回當前指標座標-子串長度,即可得到匹配到的起始位置。此時最後一位的prefixtable的值為3,把下標為3 的元素和當前指標指向元素對齊,發現要被匹配的子串已經超過了原字串,所以不可能再會有匹配的位置。

"""pattern元素和text元素對相同則繼續移動指標,假如不相同則查詢prefixtable的值,

該值對應的pattern元素是否相等,相等則繼續匹配,否則重複上面操作,

若是遇到-1的情況,則讓i,j指標往後移動

:param pattern: 要匹配的子串

:param text: 原字串

:return: 匹配到的下標值的列表

"""i = 0

j = 0

result =

text_len = len(text)

pattern_len = len(pattern)

prefix = get_prefixtable(pattern)

if text_len == 0:

return -1

while i < text_len:

if text[i] == pattern[j]:

i += 1

j += 1

else:

j = prefix[j]

# text不匹配的元素和prefix_table的頭開始匹配的情況

if j == -1:

i += 1

j += 1

# 假如j == pattern_len - 1則已經匹配到子串最後乙個元素,前面的元素都相等,

# 判斷假如text[i] == pattern[j]最後乙個元素相等則返回開頭的下標i-j當前text的位置減去匹配字串的長度,

# 為匹配的第乙個元素位置

if j == pattern_len - 1 and text[i] == pattern[j]:

j = prefix[j]

if len(result) == 0:

return -1

return result

if __name__ == '__main__':

pattern = 'ababcabaa'

text = 'cabababcabaababa'

text1 = 'abababcabaabababcabaaaba'

a = kmp(pattern, text)

print(a)

b = kmp(pattern, text1)

print(b)

print(kmp('ppppppp', text1))

print(kmp('ababcabaa', ''))

[3] # 說明下標為3第一次匹配

[2, 12] # 說明下標為3第一次匹配 說明下標為12第二次匹配

-1 # 沒找到

-1

KMP演算法(Python實現)

關於kmp演算法的原理等請參閱這篇文章 kmp演算法 c 實現 本篇文章只是對kmp用python進行了實現。1.時間複雜度分析 bf演算法的時間複雜度 在最壞的情況下,bf演算法要將目標串的每乙個字元同模式串進行比較一遍,假定目標串長度為m,模式串長度為n,總的時間複雜度為o m n 而對於kmp...

KMP演算法 python實現

兩個字串匹配,kmp演算法時間複雜度o m n 總體思想就是對於匹配子串,利用先驗知識盡可能的不重複匹配。對於子串,計算出當前字元之前字串中相同字元的個數,這樣在子串和字串當前字元匹配不成功時,就可以直接跳轉到之前字串相同的位置的下乙個,減少了匹配的次數。例如 abab,next陣列為 0,0,0,...

python實現演算法 kmp演算法python實現

kmp演算法python實現 kmp演算法 kmp演算法用於字串的模式匹配,也就是找到模式字串在目標字串的第一次出現的位置 比如abababc 那麼bab在其位置1處,bc在其位置5處 我們首先想到的最簡單的辦法就是蠻力的乙個字元乙個字元的匹配,但那樣的時間複雜度會是o m n kmp演算法保證了時...