今天資料結構課上講了kmp演算法,課上不是很理解,現在在紙上推算了一遍寫下來以供將來複習用。
void
getnext
(char s2,
int next)
else}}
intkmp
(char s1,
char s2,
int next)
else}if
(j == lens2)
else
}int
main()
;char s1[
100]
, s2[
100]
; cin >> s1 >> s2;
getnext
(s2, next)
; cout <<
kmp(s1, s2, next)
;return0;
}
首先宣告,next陣列表示我將目標串s與模擬串t一位位對比時讀到第i個s與t不同,就向前將第next[i]個拽過來取代t中的i與s對齊。注意因為next陣列不用管目標串,只有模擬串本身就可以寫出他對應的next陣列,所以我沒法考慮第i個和第next[i]個是不是相同以及是不是與s中的相同,所以寫出來代表的只是next[i]向前到頭與i向前相同位數對應全等,不包括他們自己。例如:
綜上,next陣列給出了在第i個位置不相同時,向前回溯拉至此時i的位置的索引,特徵是這兩個元素之前擁有相同的一段序列且前面的這段序列(下面我們把它叫做最長相同序列)一直到頭。
下面先說有了next陣列後怎樣程式化實現,即kmp函式。
ps一點:因為next表示在j之前擁有公共相同序列的位置,所以遞推一次後的j一定是減小的。
int
kmp(
char s1,
char s2,
int next)
//i,j是目前讀到的位置,對應元素相同則再去比下一位置,所以
//s1[i] == s2[j]時,i,j++;而當j=-1時,說明從原本讀到的j向前,
//每乙個有最長相同序列的位置本身的元素與s1中的不相等,或者根本沒有
//最長相同序列。這樣一直會到0.而next[0]一定為-1,此時應該把s2整體
//拉至i的後面,故此時的i對應j為-1,j為0時i已經++了。
else
//此時的j1與s1中的不相等,那麼看j2是否相等,以此類推。}if
(j == lens2)
//因為j=next[j]此遞推是遞減的,所以想要j走到頭一定是通過
//s1[i]=s2[j]那部分走下來,所以j到頭說明此時全等。
else
}
得到next陣列的函式:
假如此時前i已經得到了next值,next[i]=j1(假定此時j=j1),那麼從j1往前一直到頭(p2~p1)等於i前面相同長度的片段。(此時的工作都是為了求?即i+1處的next值)。此時迴圈:i掌握kmp乙個是理解利用已走過的相同序列的原理,前i個next已知後第i+1個可以利用前i個的已知資訊,利用了dp的思想。另外,kmp目前並不是最快的演算法,後來的bm演算法以及sunday演算法都要優於它。
關於KMP演算法的筆記
以前一直沒有搞懂kmp演算法,突然心血來潮,特意去網上搜尋資料下定決心弄懂,終於在一篇文章的幫助下,對kmp演算法有了自己的理解。這篇文章的出處是 the knuth morris pratt algorithm in my own words 一 什麼是kmp演算法?kmp演算法是一種改進的字串匹...
關於KMP學習筆記 2019 7 26
網上一堆 形象 部落格浪費我一堆時間,果然以前摸的魚現在還得還qaq 我來講我對於kmp演算法的自己理解 首先宣告一下,kmp演算法最關鍵的地方不在於匹配,而在於求模式串的最長匹配前字尾,在網上的其他部落格上,這個 最長匹配前字尾 的名字被替換成了 nxt 而導致部落格十分的 好懂 wdnmd我怎麼...
關於KMP演算法
複習的時候隨便寫寫的,用git太麻煩,就用csdn儲存下。kmp演算法寫起來很短,但是精髓是它的思想不太好理解,主串不用回溯,是因為模式串自己與自己比較匹配可以得出相應的next值,然後模式串向右滑動,例如,模式串abcd xxabci x在第i位失配,只需要模式串滑到d與主串繼續比較。哎呀表達得不...