KMP演算法 Python版

2022-09-04 00:27:12 字數 3513 閱讀 6950

傳統法:

從左到右乙個個匹配,如果這個過程中有某個字元不匹配,就跳回去,將模式串向右移動一位。這有什麼難的?

我們可以這樣初始化:

之後我們只需要比較i指標指向的字元和j指標指向的字元是否一致。如果一致就都向後移動,如果不一致,如下圖:

a和e不相等,那就把i指標移回第1位(假設下標從0開始),j移動到模式串的第0位,然後又重新開始這個步驟:

因為主串匹配失敗的位置前面除了第乙個a之外再也沒有a,我們為什麼能知道主串前面只有乙個a?因為我們已經知道前面三個字元都是匹配的!(這很重要)。移動過去肯定也是不匹配的!有乙個想法,i可以不動,我們只需要移動j即可,如下圖:

kmp演算法。其思想:「利用已知部分匹配這個有效資訊,保持i指標不回溯,通過修改j指標,讓模式串盡量地移動到有效的位置。」

k個字元和j之前的最後k個字元是一樣的

如果用數學公式來表示:p[0 ~ k-1] == p[j-k ~ j-1]

當t[i] != p[j]時

有t[i-j ~ i-1] == p[0 ~ j-1]

由p[0 ~ k-1] == p[j-k ~ j-1]

必然:t[i-k ~ i-1] == p[0 ~ k-1]

next[j]的值(也就是k)表示,當p[j] != t[i]時,j指標的下一步移動位置

先來看第乙個:當j為0時,如果這時候不匹配,

像上圖這種情況,j已經在最左邊了,不可能再移動了,這時候要應該是i指標後移。所以在**中才會有next[0] = -1;這個初始化。

當j為1

顯然,j指標一定是後移到0位置的。因為它前面也就只有這乙個位置

下面這個是最重要的,請看如下圖:

請仔細對比這兩個圖。

我們發現乙個規律:

當p[k] == p[j]時,

有next[j+1] == next[j] + 1

其實這個是可以證明的:

因為在p[j]之前已經有p[0 ~ k-1] == p[j-k ~ j-1]。(next[j] == k)

這時候現有p[k] == p[j],我們是不是可以得到p[0 ~ k-1] + p[k] == p[j-k ~ j-1] + p[j]。

即:p[0 ~ k] == p[j-k ~ j],即next[j+1] == k + 1 == next[j] + 1。

這裡的公式不是很好懂,還是看圖會容易理解些。

那如果p[k] != p[j]呢?比如下圖所示:

像這種情況,如果你從**上看應該是這一句:k = next[k];如下圖:

k = next[k],像上邊的例子,我們已經不可能找到[ a,b,a,b ]這個最長的字尾串了,但我們還是可能找到[ a,b ]、[ b ]這樣的字首串的。所以這個過程像不像在定位[ a,b,a,c ]這個串,當c和主串不一樣了(也就是k位置不一樣了),把指標移動到next[k]。

defkmp

(a,p):

#o(m+n)

i = 0

#主串的位置

j = 0

#模式串的位置

nextarray = getnext(p)

while i < len(a) and j < len(p):

if j == -1

or a[i] == p[j]:

i += 1

j += 1

else:#i不回溯

j = nextarray[j]#j回到指定位置

if j == len(p):

return i-j

else:

return

-1def

getnext

(p):

nextarray = [0

for i in range(len(p))]

nextarray[0] = -1

j = 0

k = -1

while j < len(p)-1:

if k == -1

or p[j] == p[k]:

j += 1

k += 1

if p[j] == p[k]:#兩個字元相等跳過

nextarray[j] = nextarray[k]

else:

nextarray[j] = k

else:

k = nextarray[k]

return nextarray

if __name__ == '__main__':

a = "abacbcdhi"

p = "cd"

res = kmp(a,p)

print(res)

KMP演算法 C 版

static void buildtable string substring,ref int next else 查詢演算法 要搜尋的字串 子串 子串在source字串中的開始位置 static int kmpsearch string source,string substring int i ...

KMP演算法 究極版

翁振宇 字串匹配 kmp演算法 演算法實現一 字串匹配的關鍵在於減少匹配次數。而kmp演算法的核心思想就是匹配陣列,根據匹配陣列的值來排程匹配字串的索引減少多餘的排程。匹配陣列就是字串具有的相同字首 字尾的最大值。比如對於字串 ababacbbb 有 ta baba cbbb 0next 10 01...

KMP演算法(Python實現)

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