傳統法:
從左到右乙個個匹配,如果這個過程中有某個字元不匹配,就跳回去,將模式串向右移動一位。這有什麼難的?
我們可以這樣初始化:
之後我們只需要比較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...