kmp演算法是一種實用的快速字串匹配演算法。
1.什麼是字串匹配?
字串匹配便是在字串s中查詢字串t.
2.如何進行匹配?
我們定義字串s為主串,長度為n;字串t為模式串,長度為m,考慮如何在主串中查詢模式串。
先來考慮暴力的方法,暴力for主串中的每個位置,對於每個位置再次for一次模式串中的每個位置,看看是否可以匹配,時間複雜度o(nm);
3.kmp演算法的本質
在暴力的演算法中,我們對主串的每個位置都進行了一次字串匹配,可是在每一次匹配時,我們每次都掃瞄了一次模式串,導致了時間的浪費。對於主串的每乙個位置,如果可以在失配後快速找到乙個可以匹配的位置,繼續進行匹配,那就可以使匹配的速度加快。(理解不了?看下面的例子。)
主串:abaabaababa
模式串:ababa
在匹配時,先從1號位置進行匹配
a b a a b a a b a b a
| | | x
a b a b a
發現無法進行匹配了,無需一位位移動,直接找到可以匹配的位置進行匹配
a b a a b a a b a b a
| x
a b a b a
發現無法匹配,再進行移動
a b a a b a a b a b a
| | | x
a b a b a
再進行移動
a b a a b a a b a b a
| x
a b a b a
移動a b a a b a a b a b a
a b a b a
發現可以匹配,得到答案。
我們發現,當在匹配時無法繼續進行匹配時,可以通過移動模式串的位置使得移動到位置的最長字尾等於原位置的最長字首,而kmp的奧妙便在於處理這個移動的方法。
4.kmp的實現方法
kmp對處理移動時引入了乙個next陣列,next[i]表示與i位置有著最長字尾的最長字首。這麼說有些繞,還是看例子中的模式串ababa。next[1]=0, next[2]=0, next[3]=1, next[4]=2, next[5]=3。next陣列還可以看作是位置i(不包括i)的字首中字首與字尾的最長公共部分。以next[4]為例,位置為4的字首為abab,它的字首與字尾的最長公共部分為ab,長度為2,所以next[4]便是2.
那麼next陣列應該怎麼求呢,先來看看以下求next陣列的方法:
1void getnext(void
) 9 }
next[i]表示的是不包括i位置的字首中字首與字尾的最長公共部分,而next[1]則不包括1位置,故為0. k記錄的是字首與字尾的最長公共部分(級next的值),之後對於next[i]的值,則可以通過遞推得出。若當前的位置為i,若當前位置可以與前乙個next值+1匹配,則當前的next值便為之前的值+1. 若當前的無法進行匹配,則k = next[k], 因為k位置的最長字首中字首與字尾的最長公共部分為next[k], 所以next[k]也為i位置的最長字首與字尾的公共部分。有while進行尋找後,再判斷當前的位置是否和k+1的位置相等,便可得出當前的next值。(關說難以理解,可以用資料手動模擬,漸漸就可以理解了。)
說完了求next陣列的方法,最重要的匹配還沒有說。那究竟如何匹配呢,還是先看**:
1void getnext(void) 9
}1011void kmp(void
) 19
}20 }
是不是和求next陣列時很像?實際上求next陣列便是模式串的自我匹配。
放一道模板題:
**如下:
1 #include2 #include3using
namespace
std;45
char s[1000001],t[1000001];6
int next[1000001
],n,m;78
void getnext(void
) 16}17
18void kmp(void
) 26}27
}2829int
main()
KMP演算法總結
kmp題目重在理解next陣列的含義 next陣列的作用 next j 記錄模式串中第 j 個字元的最長公共字首長度 重要,這是它的意義所在 第二種理解方式,當模式串與主串失配時,跳回的位置。next len 即字串 0 結束標誌的next值 單個字串匹配時與週期有關 hdu 1711 模板題 33...
KMP演算法總結
kmp演算法是用來實現模式匹配的,其時間複雜度是o m n 具體原理見 其中有用到next陣列來計算子串中公共項的位數,簡單來說,就是子串遇到不匹配時,就查next資料來決定前進幾位 移動位數 已匹配的字元數 對應的部分匹配值 1 要不要減一看next陣列第一位是不是為1,個人覺得加一後是有好處的,...
KMP演算法總結
現在假設有兩個字串a bbc abcdab abcdabde,b abcdabd。現在要在a中找b。比較暴力的方法是直接搜尋 void gosearch 上述 最核心就是while迴圈,舉兩個例子說明其作用 還是選取b串作為說明。假設現在要求next 6 那麼當前的j next 5 1 next陣列...