相比較傳統的暴力匹配字串演算法,kmp演算法有了比較大的改進,但是它卻更難理解,尤其是next陣列的求解部分。本人也反覆學習了幾次,每次弄懂但幾個月就忘了,然後就找部落格重新學,下次忘了就能看自己的博文了,哈哈。
模式串 「abcabcabda」,目標串:「abcabd」,暴力演算法中當目標串第六個字母d不匹配時,那麼將從模式串第二個字母b開始從頭匹配。我們自己判斷上面字串是否匹配時,通常的做法是遇到不匹配時,那麼我們就在模式串中找到第二個以a為開頭的匹配。kmp演算法也是這樣,但是有乙個問題,就是機器如何知道下乙個a在哪這個資訊呢?這就是next陣列的作用,在目標串中當最後乙個字元d不匹配時,這就代表著d之前的字元是匹配的,我們就知道了模式串中有abcab這個資訊,當d不匹配時,我們只需要從模式串的下乙個a開始就可以了。看到這裡可能還有點暈,沒關係,下面有更簡單易懂的**。
1.當c與d不匹配時,暴力匹配的做法時將目標串向右移動一位。如下圖
2.然後再依次比較。但是當我們自己判斷字串是否匹配時,當發現有一位不匹配時,我們不會只將目標串右移一位,而是在模式串中找到下乙個字母a。有一點是我們無法知道模式串中的a在哪,所以要利用目標串中的資訊,當第一張圖cd不匹配時,我們就知道模式串含有abcab這些字元,從下乙個a開始所以要向右移動3位。
3.如何知道不匹配時移動幾位呢,這就是next所要做的,求next也是kmp演算法的難點,知道了如何求next陣列kmp演算法也就了解七八了。下面我們來求next陣列。
4.首先我們要利用已經匹配過的字元這個資訊,比如當第二個a不匹配的時候,那麼前面abc這三個字元就知道已經匹配了,而這裡面沒有第二個a,所以當第二個a不匹配時,要向右移動4位;
5.當第二個b不匹配時,abca已經匹配,含有a,所以只要移動3位即可;
6.當d不匹配時,abcab已經匹配過了,含有ab,所以也只要移動3位即可,注意這裡是要含有ab兩個,不能只是a,向下面這種情況就不可以;
7.這裡最後改為acd,當d不匹配時,雖然找到了a,但是ab與ac對應不上,所以還是要向右移動6位。這個其實也就是書中所說的最大的字首等於字尾的意思。
public static void main(string args)
private static void getkmp(int next, string model, string searchstr) else
}if (i==searchstr.length())else
}/**
* 得到next陣列
*/private static void getnext(int next, string searchstr) else }}
kmp演算法 簡單易懂
kmp字串 給定乙個模式串s,以及乙個模板串p,所有字串中只包含大小寫英文本母以及阿拉伯數字。模板串p在模式串s中多次作為子串出現。求出模板串p在模式串s中所有出現的位置的起始下標。輸入格式 第一行輸入整數n,表示字串p的長度。第二行輸入字串p。第三行輸入整數m,表示字串s的長度。第四行輸入字串s。...
通俗易懂的KMP演算法詳解
1.bf演算法 首先,簡單介紹bf 簡單的模式匹配法 假設主串為 abcbcglx 長度為m,模式串為 bcgl 長度為n。通常先從主串的下標0開始與子串的下標0開始匹配,如果匹配失敗,則從主串的第二個元素開始與子串的第乙個元素進行匹配。例如 第一次匹配 剛開始先用主串下標0 a 與子串下標0 a ...
通俗易懂的KMP演算法詳解
有些演算法,適合從它產生的動機,如何設計與解決問題這樣正向地去介紹。但kmp演算法真的不適合這樣去學。最好的辦法是先搞清楚它所用的資料結構是什麼,再搞清楚怎麼用,最後為什麼的問題就會有恍然大悟的感覺。我試著從這個思路再介紹一下。大家只需要記住一點,pmt是什麼東西。然後自己臨時推這個演算法也是能推出...