經典模式匹配演算法

2021-06-21 15:08:40 字數 3090 閱讀 3348

模式匹配演算法的**只有十四行,看了兩天,終於看懂了,吐槽一下,演算法太經典了。

首先要了解一下串操作中模式匹配演算法的作用是什麼,簡單的說就是從乙個主串中需找特定的字元子串,要尋找的字元子串稱為模式串。自然很容易想到乙個方法就是:直接拿模式串在主串中移動,一旦移動到某乙個位置模式子串所有的字元與主串中的字元都相同,那麼就找到了字串,該方法成為fm演算法。記主串為s1s2……sn,模式串為p1p2……pm。如圖一所示:

圖一:fm

演算法串匹配

這種演算法很簡單,但是時間上付出了很大的代價,每一次匹配不成功,都必須回溯到原來的位置的下乙個位置重新匹配,複雜度為o(m*n)

。模式串匹配是在該方法的基礎之上進行改進,想辦法不需要在主串中回溯,即希望主串中每個字元值匹配一次,

kmp演算法是可以做到的,下面我們就來看看

kmp。

假設拿模式串和主串進行匹配,從模式串的第乙個字元開始,如果相等,則進行下乙個字元的比較……一直進行下去直到兩個字元不等,記錄此時主串位置為i

,模式串位置為

j,即第i和第

j個位置失配。這樣我們想辦法讓主串的

i保持不回溯,其實如果』pj-k+1pj-k+2……pj-1』=』p1p2……pk-1』(在j

之前:字首

=字尾,注意這裡前字尾相等的長度要取最大值),只需將模式串右移,(令

next[j]=k

)就可以保持

i不回溯了(注意這裡我們討論從第乙個字串開始,不考慮

0下標的陣列)。如圖二所示:

圖二:kmp模式串匹配

總結起來kmp

演算法與fm

演算法的不同就是,

fm在失配時需要回溯,而

kmp在

i-j失配時不需要回溯,只需確定新的

k,使得下一次

next[j]=k

,重新進行匹配,一直這樣下去……確定

k的準則就是

j之前的:字首等於字尾pj-k+1pj-k+2……pj-1』=』p1p2……pk-1』。

下面就來談談模式串如何用**實現字首等於字尾找next[j]=k

。請跟上節奏,有點繞:

因為每乙個位置都有乙個next

值,於是可以做如下假設:設模式串第

i個位置的

next[j]=k

,即有:

『pj-k+1pj-k+2……pj-1』  =  』p1p2……pk-1』              (1)

接下來看一下next[j+1]

如何取值?

1)如果pj=pk,則表明

』pj-k+1pj-k+2……pj-1pj』  =  』p1p2……pk-1pk』            (2)

所以next[j+1]= next[j]+1= k+1

2)如果pj != pk,則表明

『pj-k+1pj-k+2……pj-1』  =  』p1p2……pk-1』             (3)

pj  !=  pk                                  (4)

用下圖不同顏色表示相等的字首和字尾

圖三 :模式串示意圖

這時候主模式串又可以看做自己的模式串,即拿自身的字首去找相同的字尾。由於已經有(3

)和(4

)式成立。要從圖三種找到和字尾

2段相同的

1段,要知道在圖中綠色部分是相同的子串,所以我們要拿

p1p2……pnext[k]去與2

段匹配(注意1段和

3段黑色代表臨界的值,不相等,故可以拿

1段去與

2段匹配),是不是有點繞,就這個地方,好好想想,想清楚了接下來就簡單了。這個地方就是乙個經典的遞推過程。總結起來就是需要找

next[k]

,此時:

next[j+1]=next[k]+1,

得到next[j+1]

之後重複以上所有過程。

當然有可能我們找不到next[k]

,那麼直接讓模式串右移一位就行了,即

next[j+1]=1。

c++**實現過程如下:

void

get_next

(hstrings,

intnext)

else j

=next[j

];//

其實這就是乙個遞推過程

} }kmp演算法的改進

上面定義的next

尚有缺陷,因為如果模式』aaaab』(next[j]為

01234

)在和主串』aaabaaaab』匹配時,當i=4,j=4

時失配,由

next[4]=3

可知i=4,j=3

、i=4,j=2

、i=4,j=1

都要進行匹配,但實際上模式串中第

1,2,3

個字元和第

4個字元都想等,因此不需要再和主串中的第

4個字元相比較,而可以將模式一次向右直

]接滑動

4個字元的位置進行

i=5,

j=1時的字元比較。

這就是說,如果按照之前的定義next[j]=k

,而模式中

pj=pk,則主串中字元si和pj比較不等時,不需要再和pk進行比較,而可以直接和pnext[k]進行比較。換句話說,此時的next[j]

應該和next[k]

相同。

改進kmp

**實現如下

void

get_next

(hstrings,

intnext)

else j

=next[j

];//這就是乙個遞迴過程 }

}

模式匹配演算法

brute force演算法 kmp演算法 kmp演算法的改進 模式匹配 子串的定位操作被叫做串的模式匹配。串相等 串長度相等且各個對應位置的字元都相等。當兩個串不相等時,判斷兩個串大小的方法 給定兩個串 s1 a1a2a3a4 an 和s2 b1b2b3b4 bm 當滿足以下條件之一時,s1n存在...

演算法 模式匹配

你有兩個字串,即pattern和value。pattern字串由字母 a 和 b 組成,用於描述字串中的模式。例如,字串 catcatgocatgo 匹配模式 aabab 其中 cat 是 a go 是 b 該字串也匹配像 a ab 和 b 這樣的模式。但需注意 a 和 b 不能同時表示相同的字串。...

KMP模式匹配演算法以及普通模式匹配演算法

if return value 1 the indexsubstr is not exist else the indexsubstr is exist.int indexsubstr char substr,char str,int pos 0 printf lensubstr d n lensu...