目錄
一、找出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演算法保證了時...