串的模式匹配演算法主要有兩種,一是簡單模式匹配,而是kmp演算法。
簡單模式匹配演算法很容易理解,每一次從主串的第乙個位置起和模式串的第乙個字元開始比較,如果相等就按照順序一直比下去,如果不相等就把模式串和第二個位置開始繼續進行比較,最後若匹配成功則返回主串中與模式串匹配的第乙個字元的位置,雖然簡單易懂也容易實現,但過程及其繁瑣,有許多冗餘的步驟降低了匹配效率。
因此採用無回溯效率更高kmp演算法,它哪哪都好除了看不懂,書本上的話簡直沒法看,感覺在講天書!!!各種下標各種公式根本看不懂。
以下是我對kmp演算法的個人理解:
kmp和簡單模式匹配演算法的區別就是,主串和模式串匹配不成功時,簡單模式匹配得屁顛屁顛跑回去,從上一次比較的下乙個字元開始繼續比較,就算中間有大部分比較過得,就算明知道第乙個字元就不匹配的但我還是得去比,沒辦法,所以效率低下且各種回溯。
而kmp演算法是當在某個位置匹配不成功的時候可以根據之前匹配結果,從模式串的另乙個位置開始匹配字串,而不必從頭開始,只需要將模式串後移即可,大大的提公升了匹配效率,但如何確定後移的位置點呢?
t1 t2 ......ts ts+1 ts+2 .... ts+j-k-1 ts+j-k .... ts+j-1 ts+j ....
p0 p1 p2 ..... pj-k-1 pj-k ..... pj-1 pj ......
p0 p1 .... pk ........
如上,只要求得k值就能知道模式串後移的目標位置。為方便說明,取陣列從1開始計數。在這裡定義next[j]陣列,1接下來才是重點:
眾所周知,kmp演算法的靈魂就是求next陣列和nextval陣列,不管各種資料怎麼說,以我自己的思路先走一遍求解next陣列的步驟:
以例題來說明:
模式串:ababaaababaa
口訣①:當j=1的時候,next[j]=0。
口訣②:子串的前字尾沒有匹配部分,並且子串不為空,next[j]=1,用人話來說就是模式串裡面沒有任何乙個字元能夠匹配成功,沒有任何重複元素,就跟abcd這種一樣,遇見這種給它賦1就完事了。
口訣③:子串前後有匹配部分,就去數一數匹配部分有多長,比如aba,倆a匹配了,在一起互gay,長度為1,那麼就給next賦匹配子串長度+1!!!即next[j]=2
例題計算步驟:
1.j=1,next[1]=0
2.j=2,模式串為a,沒有匹配元素,next[2]=1
3.j=3,模式串為ab,沒有匹配元素,next[3]=1
4.j=4,模式串為aba,前後串有匹配的a,next[4]=1+1=2
5.j=5,模式串為abab,ab匹配,next[5]=2+1=3
最後求解的答案為:
0 1 1 2 3 4 2 2 3 4 5 6
再然而,這種kmp方法還是有缺陷,一些情況下也會產生冗餘比較,原因不加以說明,直接記錄步驟。
還是模式串ababaaababaa.
用p1~pm來表示模式串的第i個位置處的字元(1另取k(-1比較pi與pk
若相等,則繼續判斷k值是否為0,若k=0,則nextval[j]=k,若k!=0,則nextval=nextval[next[j]].
若不等,nextval[j]=k=next[j]
解題步驟:
1.j=1
nextval[1]=0
2.j=2
p2=b
pk(k=next[2]=1)=p1=a
pi!=pk,nextval[j]=k=1
3.j=3
p3=a
pk(k=next[3]=1)=p1=a
pi=pk,nextval[j]=nextval[next[3]]=0
最後結果為:
0 1 0 1 1 2 0 1 0 1 0 2
理解KMP演算法
由暴力匹配引入kmp演算法 問題 有乙個文字串s,和乙個模式串p,現在要查詢p在s中的位置。如果用暴力匹配的思路,並假設現在文字串s匹配到 i 位置,模式串p匹配到 j 位置,則有 示例 上面s,下面p 比如從a這裡開始匹配上了 一直這樣匹配下去 到這裡匹配不上了 就回滾回去重新開始 這種回滾的問題...
對KMP演算法的理解
kmp演算法是一種高效的模式匹配演算法,複雜度可以達到o m n 而普通模式匹配演算法的複雜度為o m n 普通模式匹配演算法 從主串的第乙個字元 或者給定的第pos個字元 開始和子串的第乙個字元開始比較,若相等,則繼續比較後面的字元。若不相等,則從主串本次開始比較的字元的下乙個字元開始,與子串的第...
對KMP演算法的理解
kmp演算法是一種高效的模式匹配演算法,複雜度可以達到o m n 而普通模式匹配演算法的複雜度為o m n 普通模式匹配演算法 從主串的第乙個字元 或者給定的第pos個字元 開始和子串的第乙個字元開始比較,若相等,則繼續比較後面的字元。若不相等,則從主串本次開始比較的字元的下乙個字元開始,與子串的第...