# Knuth–Morris–Pratt
###### tags: `Algorithm` `Knuth–Morris–Pratt`
**step 1 get Partial Match Table 找出最長公共前綴表**
Q1:為什麼需要這個表?
這個表的用意在當匹配失敗時可找到上一個相同字串,而不是重頭開始重新比對
ex: abcde
前綴 :
abcd
abc
ab
a
後綴 :
bcde
cde
de
e
abcdabc
a -> 0
ab -> 0
abc -> 0
abcd -> 0
abcda -> 1
abcdab -> 2
abcdabc ->3
PMT
a b c d a b c
0 0 0 0 0 1 2
為了程式設計的方便, 不直接使用PMT陣列,而是將PMT陣列向後偏移一位
第0位的值,將其設成了-1,這只是為了程式設計的方便,並沒有其他的意義。
a b c d a b c
-1 0 0 0 0 0 1 2
**step 2 mapping**
target string : abceabcdabc
mapping string : abcabc
a b c e a b c d a b c
a b c d a b c
比對到'e'與'd'時發現不相同
則將mapping table移動到'd'的前綴表值
d的前綴表值為0
a b c e a b c d a b c
a b c d a b c
再次筆對'e'與目前mapping table且不相同
則找到'a'的前綴表值為-1即表示往後推進一位
a b c e a b c d a b c
a b c d a b c
**程式面**
取得前綴表
a 0
ab 0
abc 0
abcd 0
abcda 1 <-
abcdab 2
abcdabc 3
key1 : 取下一層新增的元素 與 上一層的共用元素的下一個相比
ex
s1 = abcda p_len = 1
s2 = abcdab
當s2要滿足PMT時 s2[prefix] 勢必要等 新增的元素 s2[last] = 'b'
key2: 當下一層沒有匹配時需往上一層上上一層...回推到 index = 0
回推的方法為 找到上上層prefix table所指向的char
s1 = abcdab p_len = 2
s2 = abcdaba
step 1
s2[p_len] <> s2[last]
step 2
p_len = prefix_table [p_len-1]
s2[p_len] <> s2[last]
.... 直到找到index為0