模式串匹配 KMP演算法

2022-04-18 18:04:26 字數 2013 閱讀 6744

kmp是對字首暴力搜尋的改進,基於的想法其實是很樸素的。首先我們來看一下暴力搜尋。

char* bf(char *src, char *pattern)

else

}if(*pattern_temp == '

\0') return

src;

else

return

null;

}

如果匹配失敗,則將關鍵字向右滑動乙個字元,從頭開始匹配關鍵字,匹配成功則有src[i,i+1,......i+m] == p[0,1,......m]。bf的時間複雜度是o(m*n)。kmp改進的想法很樸素,能不能不是每次移動乙個距離,每次多移動幾個距離不就可以提高效率了麼,但是每次多移動幾個呢?kmp演算法就是解決每次移動幾個的問題。

假設暴力搜尋時關鍵字在匹配到p[j]字元時失敗了,即src[i,i+1,......,i+j-1] == p[0,1,......j-1](1), src[i+j] != p[j],則按照暴力搜尋的方法將關鍵字向右滑動乙個字元,即從src[i+1]開始從新匹配。

但是我們假設關鍵串有如下特徵:

p[0,1.....j-2] != p[1,2,......j-1](2),則(1)可知p[0,1......j-2] != src[i+1,i+2,......,i+j-1],所以將關鍵串向右滑動乙個字元從src[i+1]開始匹配肯定失敗,所以在我們知道(2)式的情況下,就可以直接跳過向右滑動乙個字元,那到底滑動幾個字元呢?如果我們知道了子串p[0,1,......next(j-1)](next(j-1)又叫做j-1的失效函式),既是p[0,1,......j-1]的最長真字首又是p[0,1,......j-1]最長字尾,那我們就可以將關鍵字向右滑動j-1-next(j-1)個字元,並且認為關鍵串的前next(j-1)個字元已經匹配成功,繼續從src[j]開始匹配(這個思想同樣應用於求next(j)的演算法中,後面的**中可以看到)。所以整個kmp演算法的關鍵就是求得每乙個next(j), j = 0......m,這樣就可以知道在j+1匹配失敗的時候,應該將關鍵字向右滑動幾個字元位置。可以證明kmp演算法的時間複雜度是o(m+n)。

void next(char *pattern, int *next)

else next[s] = -1

; }

}

得到上面的next(j)後,就可以在o(n)的時間內掃瞄src字串,以判斷該關鍵串是否出現在其中。關鍵串沿著匹配字串滑動,不斷嘗試將關鍵字的下乙個字元與被匹配字串的下乙個字元匹配,逐步推進。如果在匹配了j個字元後無法匹配,那麼將關鍵字向右滑動j-next(j)個位置,並且前next(j)個字元已經匹配成功,從src[j+1]繼續匹配。

char* kmp(char *src, char *pattern)

if(pattern[s+1] == '

\0') return &src[i] - pattern_size +1

; }

return

null;

}

說到kmp就不得不說ac自動機,其實理解了kmp的思想,即找出子串p[0,1,......next(j-1)],既是p[0,1,......j-1]的最長真字首又是p[0,1,......j-1]最長字尾,也就不難理解ac自動機。ac自動機又叫aho-corasick演算法,是aho和croasick對kmp演算法的推廣,可以在乙個文字串種識別乙個關鍵字集合中的任何關鍵字。由於是關鍵字集合,所以採用了trie-tree來儲存關鍵字,每個節點的失效函式稍微不同於kmp的失效函式,即狀態next(j)對應於最長的、既是串pattern[0,1......,j]的字尾,又是某個關鍵字的字首的字串。對於ac自動機,你可以理解為是在求失效函式和匹配過程中考慮了關鍵字集合的kmp或者kmp是ac自動機的特例,但是核心思想就是子串p[0,1,......next(j-1)],既是p[0,1,......j-1]的最長真字首又是p[0,1,......j-1]最長字尾,ac自動機只是描述關鍵字集合的一種方法。關於ac自動機,dsqiu的部落格有乙個比較好的實現,有興趣可以看一下。

KMP 模式串匹配演算法

這兩天讀了july的kmp,覺得很受益,寫下以作備忘。kmp最重要的就是求出next陣列,而next陣列則是通過不斷比較 str2 k 與 str2 j 來確定下乙個字元對應的 next數值 相等則直接next j k 不相等則令k next k 進行遞推直到出現 str2 k str2 j 相等的...

串 KMP模式匹配演算法

樸素模式匹配演算法就是簡單的二重迴圈,第一重迴圈主串s從1到n,然後第二重迴圈子串t從1到m進行匹配判斷,時間複雜度為o n m 1 m kmp演算法的核心思想是 第一 如果子串前r個字元均不相等,且子串前r個字元與主串某連續的r個字元匹配,但子串第r 1就不匹配了,則主串的匹配下標可以直接向前跳r...

串的模式匹配 KMP演算法

一 kmp演算法的思想 由d.e.knuth j.h.morris和v.r.pratt共同提出了乙個改進演算法,消除了brute force演算法中串s指標的回溯,完成串的模式匹配。時間複雜度為o s.curlen t.curlen 這就是knuth morris pratt演算法,簡稱kmp 演算...