發現學了好久了kmp了,模板卻總是背不會,感覺自己還是沒有理解深刻,僅以此作為複習…
給定乙個模式串s長度為m,和模板串p長度為n,求解模板串p在模式串s**現的位置
模板串p需要同模式串s匹配很多次,當乙個字元匹配失效時,傳統的演算法往往模板串p會整個從頭開始,導致演算法的時間複雜度是o(m
∗n)o(m*n)
o(m∗n)
,kmp演算法通過構造模板串p的next陣列,使其進行"跳躍"著的匹配,將其時間複雜度優化到 o(m
+n)o(m + n)
o(m+n)
。next陣列
next[k] 含義:前k個元素具有相同前字尾的長度。
當第k個字元匹配失效時,應該跳轉到的下乙個位置為next[k]。因為雖然第k個字元匹配失效,但是前k個字元匹配成功,那麼此時已經匹配的字串的字尾就可以當作下一次匹配的字首,當然此處的前字尾相同且長度盡可能大,這樣的跳轉優化了複雜度。
例子:求 abababca 的 next陣列
charab
abab
caindex01
2345
67next
-1
0
01
0
3
4
0
next陣列的求法很多種,感覺我寫得比較古老…
觀察next陣列:
1)通常第乙個next[0] = -1
2)next[k]為前k個字元相同前字尾的長度,由於是長度,而下標是從0開始的,所以其實next[k]是跳轉到具有相同字首字串的後乙個字元進行下一次匹配的。
畫圖理解:
**求next
void
getnext
(char
*p)else j = next[j];}
}
next陣列的優化當第 p[ i ] 與 s 匹配失效時會跳轉到 next[ i ],但是如果 p[ i ] = p[next[ i ]],那麼匹配依然失效,所以需要遞迴的跳轉即next[ i ] = next[next[ i] ]
void
getnext
(char
* p)
else j = next[j];}
}
查詢p第一次出現在s的位置int i =
0, j =0;
int m =
strlen
(s), n =
strlen
(p);
while
(i < m && j < n)
else j = next[j];}
// 模板串p的最後乙個字元p[n-1]匹配成功後,++j後j = n然後退出迴圈
if(j == n)
查詢p出現在s的所有位置int i =
0, j =0;
// 注意 j = 0
while
(i < m)
else j = next[j];if
(j == n)
}
由於next陣列的含義是具有相同前字尾的長度,所以往往用來求迴圈節
使用方法:
1)求整個字串迴圈節長度 :r = n - next[n]
2)補全為迴圈節的不斷重複需要填充的字元個數:
當 r != n && n % r == 0 : cnt = 0
否則,cnt = r - n % r
3)求每個字首的迴圈節:i - next[ i ]
4)利用迴圈節不斷向前遞迴
KMP演算法模板與解析
全部資料結構 演算法及應用課內模板 將kmp演算法,就要先講講它是用來幹什麼的,為什麼叫這個名字,暴力的演算法又是怎樣的 kmp是三人knuth,morris,pratt,他們仨發明了這個演算法,所以叫kmp。不要驚訝。然後它是用來解決字串的模式匹配問題 大白話就是找子串 舉個例子說就是,給你乙個主...
KMP演算法(模板)
time limit 1000ms memory limit 65536k 有疑問?點這裡 給定兩個字串string1和string2,判斷string2是否為string1的子串。輸入包含多組資料,每組測試資料報含兩行,第一行代表string1 長度小於1000000 第二行代表string2 長...
KMP演算法模板
在文字t 1.n 中找到某個模式p 1.m 所有出現的位置被稱作字串匹配問題 m n p3375 模板 kmp字串匹配 這道題在洛谷上的評級居然是普及 普及?qvq 實現起來還是比較簡單的,只不過有很多細節可以有很多種寫法,看別人的 容易凌亂。理解起來比較困難的部分是如何get next 不建議初學...