模式匹配演算法的**只有十四行,看了兩天,終於看懂了,吐槽一下,演算法太經典了。
首先要了解一下串操作中模式匹配演算法的作用是什麼,簡單的說就是從乙個主串中需找特定的字元子串,要尋找的字元子串稱為模式串。自然很容易想到乙個方法就是:直接拿模式串在主串中移動,一旦移動到某乙個位置模式子串所有的字元與主串中的字元都相同,那麼就找到了字串,該方法成為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...