常用演算法 模式匹配(KMP)

2021-07-16 04:21:18 字數 1902 閱讀 9222

在乙個字串中查詢乙個子字串有很多方法,最簡單容易想到的演算法便窮舉,但這樣的情況下演算法複雜度為o(m * n)。

而kmp是一種最常見的改進演算法,它可以在匹配過程中失配的情況下,有效地多往後面跳幾個字元,加快匹配速度。

kmp演算法中有個陣列,叫做字首陣列,也有的叫next陣列,每乙個子串有乙個固定的next陣列,它記錄著字串匹配過程中失配情況下可以向前多跳幾個字元,當然它描述的也是子串的對稱程度,程度越高,值越大,當然之前可能出現再匹配的機會就越大。

先來個圖表來表示一下next陣列的求解方式:

可是如何去求next陣列每個陣列元素的值呢?

-1. 逐個查詢對稱串

比如i = 0時,串對應的字元是a,不存在對稱,所以next[0] = 0;

同樣的,i = 1, 2, 3時 ag, agc, agct均不存在對稱,所以next[1…3] = 0;

而i = 4時,agcta串的字首a和字尾a相等,長度為1,所以next[4] = 1;

再比如i = 6時,agctagc的字首agc和字尾agc相等,長度為3,所以next[6] = 3;

而i = 7時,agctagca只有字首a和字尾a相等,長度為1,所以next[7] = 1;

之後,便可以次類推。

既然已經可以人工的推出這個next陣列的值了,那麼程式設計應該也可實現了:

程式設計思想如下:

1) 當前面字元的前乙個字元的next值為0時,只要將當前字元與子串第乙個字元進行比較。前面都是0,說明都不對稱了,到當前位置時只是多加了乙個字元,要對稱的話最多是當前的和第乙個對稱。此時,如果當前字元和第乙個相等,那個該位置的next值為1,否則為0;

2) 依此,可以總結乙個規律,不僅當前乙個字元的next值為0時,如果前面乙個字元的next值是1,那麼我們就把當前字元與子串第二個字元進行比較,因為前面的是1,說明前面的字元已經和第乙個相等了,如果這個又與第二個相等了,說明next就是2了;

3) 同2)中所說如果一直相等,就一直累加。

說到這裡,上面情況理解起來應該沒什麼問題,現在的問題是如果遇到下乙個不等,該怎麼進行處理?

比如i = 14時,該位置的前乙個字元的next值為7,但該位置的next值按照最大公共前字尾(agct)的規則來看,長度為4,其next的值為4。

在這裡相當於重新尋找i = 14,更小的對稱性,那麼:

1)如果要存在對稱性,那麼對稱程度肯定比前乙個字元 的對稱程度小,所以要找個更小的對稱;

2)要找更小的對稱,必然在對稱內部還存在子對稱,而且當前字元還必須緊接著在子對稱串之後;

所以,agctagc 和 agctagc對稱,agc、agc、agc、agc、對稱。

演算法實現與測試:

#include

#include

#include

#include

#include

#include

#include

using namespace std;

//求next陣列

void create_next(const string &seq,int

*next)

next[i] = k;

}}//kmp演算法實現

int kmp(const string &str,const string &sub,int *next)

if (q == m)

}

return i - m + 1;

}int main()

模式匹配 KMP演算法

字串匹配演算法 include includeusing namespace std define ok 1 define error 0 define overflow 2 typedef int status define maxstrlen 255 使用者可在255以內定義最長串長 typed...

模式匹配KMP演算法

前些日子在為目前該學習什麼而苦惱,就問了一下已經從事多年軟體開發的表哥,他說乙個程式設計師要走的遠,就要學好資料結構和演算法,於是我就重新開始學習資料結構和演算法了 拿起以前上過的資料結構看,看到第四章串的模式匹配時,頗感興趣,就寫了一下程式,實踐了一下。感覺還蠻爽,於是就把以下幾個重要的函式放在此...

KMP模式匹配演算法

首先,這是由knuth morris和prattle三人設計的線性時間字串匹配演算法。這裡就不仔細的講解,網上有更好的講解,在這推薦幾個自己當時學習的kmp所看到的較好理解的 這裡附上自己所學的 includeusing namespace std s 是主串 p 是模式串 int next 100...