假設文字t = y1y2y3....yn, 模式 p = p1p2p3...pm, 傳統的匹配演算法把位移為0,1,...n-m時的文字依次跟p比較,每次比較最多花費o(m)的時間,演算法的複雜度為o((n-m+1)*m)。
傳統模式匹配演算法沒有利用匹配過的資訊,每次都從頭開始比較,速度很慢。而kmp演算法充分利用了之前的匹配資訊,從而避免一些明顯不合法的位移,加快匹配過程。在字串o中尋找f,當匹配到位置i時兩個字串不相等,這時我們需要將字串f向前移動。常規方法是每次向前移動一位,但是它沒有考慮前i-1位已經比較過這個事實,所以效率不高。事實上,如果我們提前計算某些資訊,就有可能一次前移多位。假設我們根據已經獲得的資訊知道可以前移k位,我們分析移位前後的f有什麼特點。我們可以得到如下的結論:
a段字串是f的乙個字首。
b段字串是f的乙個字尾。
a段字串和b段字串相等。
所以前移k位之後,可以繼續比較位置i的前提是f的前i-1個位置滿足:長度為i-k-1的字首a和字尾b相同。只有這樣,我們才可以前移k位後從新的位置繼續比較。
所以kmp演算法的核心即是計算字串f每乙個位置之前的字串的字首和字尾公共部分的最大長度(不包括字串本身,否則最大長度始終是字串本身)。獲得f每乙個位置的最大公共長度之後,就可以利用該最大公共長度快速和字串o比較。當每次比較到兩個字串的字元不同時,我們就可以根據最大公共長度將字串f向前移動(已匹配長度-最大公共長度)位,接著繼續比較下乙個位置。事實上,字串f的前移只是概念上的前移,只要我們在比較的時候從最大公共長度之後比較f和o即可達到字串f前移的目的。
理解了kmp演算法的基本原理,下一步就是要獲得字串f每乙個位置的最大公共長度。這個最大公共長度在演算法導論裡面被記為next陣列。
在這裡要注意一點,next陣列表示的是長度,下標從1開始;但是在遍歷原字串時,下標還是從0開始。假設我們現在已經求得next[1]、next[2]、……next[i],分別表示長度為1到i的字串的字首和字尾最大公共長度,現在要求next[i+1]。由上圖我們可以看到,如果位置i和位置next[i]處的兩個字元相同(下標從零開始),則next[i+1]等於next[i]加1。如果兩個位置的字元不相同,我們可以將長度為next[i]的字串繼續分割,獲得其最大公共長度next[next[i]],然後再和位置i的字元比較。這是因為長度為next[i]字首和字尾都可以分割成上部的構造,如果位置next[next[i]]和位置i的字元相同,則next[i+1]就等於next[next[i]]加1。如果不相等,就可以繼續分割長度為next[next[i]]的字串,直到字串長度為0為止。
計算完成next陣列之後,我們就可以利用next陣列在字串o中尋找字串f的出現位置。匹配的過程和求next陣列的過程其實是一樣的。假設現在字串f的前i個位置都和從某個位置開始的字串o匹配,現在比較第i+1個位置。如果第i+1個位置相同,接著比較第i+2個位置;如果第i+1個位置不同,則出現不匹配,我們依舊要將長度為i的字串分割,獲得其最大公共長度next[i],然後從next[i]繼續比較兩個字串。核心是選取子串的next[i]位與主串的下一位去比較,即每次從子串提取的比較字元可不是一次的,而是可跳躍式選取的。即主串不回溯(但可能會在原位置停留),子串可回溯。
現在我們來看kmp的演算法時間複雜度,在構建next陣列的時候,可以看到計算每個位置的最大公共長度其演算法時間複雜度為o(1),那麼對於長度為n的子串而言,其演算法時間複雜度為o(n)。由於在kmp演算法中對於長度為m的主串進行匹配,主串不回溯,所以其演算法時間複雜度為o(m)。然後看整個kmp演算法,構建next陣列與子串匹配為線性關係,則kmp演算法的複雜度是o(n+m)。
KMP演算法小結
posted on 2011 06 14 byhuangchao 主要看了這裡,感覺講的十分的不錯,總結一下。首先宣告要搜尋的串為s,設長度為n,要匹配的串為m,設長度為m.先考慮暴力的演算法,暴力的演算法是遍歷s的每乙個字元,然後從這個字元開始和m串進行匹配。時間複雜度為o nm 怎麼在此基礎上進...
KMP演算法小結
主要看了這裡,感覺講的十分的不錯,總結一下。首先宣告要搜尋的串為s,設長度為n,要匹配的串為m,設長度為m.先考慮暴力的演算法,暴力的演算法是遍歷s的每乙個字元,然後從這個字元開始和m串進行匹配。時間複雜度為o nm 怎麼在此基礎上進行優化?假設現在從某個位置 設為s 開始和m串進行匹配,如果匹配不...
KMP演算法小結
文字串長度為n,模式串長度為m,匹配過程的時間複雜度為o n 計算next的o m 時間,kmp的整體時間複雜度為o m n 步驟 文字串s bbc abcdab abcdabcdabde 模式串p abcdabd 1.尋找p的 最長公共元素表 前字尾最長序列長度 失配時,模式串向右移動的位數為 已...