我們將待匹配的字串稱為主串,用來匹配的字串稱為模式串(模式串長度小於等於主串長度)。
設模式串p
為"orzzorzo"
,主串s
為"orzzorqworzzorzo"
,使用樸素演算法進行匹配時("-"
表示匹配成功,"|"
表示在此字元失配):
orzzorqworzzorzo
------|
orzzorzo
首先,將兩串對齊,從左到右匹配p
與s
的每一位字元。當失配時,將模式串右移一位:
orzzorqworzzorzo
| orzzorzo
此時發現第一位就失配了,還要繼續右移……
更好的策略是當'q'
失配時,直接對齊模式串開頭"or"
,不必回溯重新匹配:
orzzorqworzzorzo
--|orzzorzo
而接下來這次失配後,本來需要將模式串與'r'
對齊,但根據上面的思路將模式串直接與'q'
對齊即可:
orzzorqworzzorzo
|orzzorzo
通過上述例子,可以發現如果部分匹配的串有對稱的前字尾,則我們可以直接將模式串中部分匹配串的字首與主串中部分匹配串的字尾對齊,如:
orzzorqworzzorzo
------|
orzzorzo
例子中的部分匹配串為"orzzor"
,有對稱的前字尾"or"
,則可以直接將部分匹配模式串的字首"or"
與部分匹配主串的字尾"or"
對齊。
再來乙個例子,模式串為"qqwqqa"
,主串為"qqwqqwqqa"
qqwqqwqqa
-----|
qqwqqa
此時的部分匹配串為"qqwqq"
,它有兩個對稱的前字尾,分別是"qq"
和"q"
,如果以"q"
對齊,可以得到:
qqwqqwqqa
-|qqwqq
在模式串第二個'q'
處失配後,繼續匹配,最終結果是匹配失敗。
然而,如果我們以"qq"
對齊,則有:
qqwqqwqqa
------
qqwqqa
結果是匹配成功。
(事實上我們也不會先對齊"q"
,因為先對齊"qq"
可以更快匹配完
這個例子告訴我們,當部分匹配串有多個對稱前字尾時,需要選擇最長的,以保證匹配結果的正確。
定義nxt
陣列,長度等於模式串長度,它的第i
個成員代表以模式串前i
個字元作為部分匹配串時,部分匹配串的最長對稱前字尾長度(字首末尾的位置)。
匹配步驟:
如果當前字元匹配(p[j + 1] == s[i + 1]
),則繼續匹配下乙個字元(i++, j++
);
如果當前字元失配(p[j + 1] != s[i + 1]
),則直接將模式串右移到字首與字尾對齊的位置(j = nxt[j]
)直到匹配或者找到了 0(移動模式串,使模式串中部分匹配串的字首與主串中部分匹配串的字尾對齊)。
定義nxt
陣列,長度等於模式串長度,它的第i
個成員代表以模式串前i
個字元作為部分匹配串時,部分匹配串的最長對稱前字尾長度(字首末尾的位置)。
由定義可得:
i | 1 | 2 | 3 | 4 | 5 | 6 | 7
p | q | q | w | q | q | q | a
nxt | 0 | 1 | 0 | 1 | 2 | 2 | 0
推導方法與 kmp 類似,用自己字首子串和自己匹配:
令j = nxt[i]
;
如果當前字元和最長字首下乙個字元匹配(p[j + 1] == p[i + 1]
),則nxt[i + 1]
為nxt[i] + 1
即j + 1
;
如果當前字元和最長字首下乙個字元失配(p[j + 1] != p[i + 1]
),則繼續對比第i + 1
個字元與nxt[nxt[i]] + 1
個字元,以此類推(即j = nxt[j]
繼續對比p[j + 1]
與p[i + 1]
),一直向前找直到匹配或者找到了 0。
如模式串:agctagcagctagct
加粗的'a'
與最後乙個't'
不匹配,此時向前找找到"agctagc"
的最後乙個'c'
的對稱位置的後乙個字元,發現是't'
,則找到前後的"agct"
是乙個對稱的前字尾。
const int maxn = 1000000;
inline int kmp(char *s, char *p)
int res = 0; // 匹配次數
for (int i = 1, j = 0; i <= ls; i++)
} return res;
}
(基本照搬x 學習筆記 KMP
kmp用於在乙個字串中尋找乙個模式串。kmp詳細講解 一 演算法思想 下標從0開始 當我們需要在乙個字串中s找乙個模式串p是否出現的時候,最容易想到的就是暴力 列舉左端點,然後從這個點開始匹配,失敗則換下乙個左端點 如圖所示 我們先匹配了a b c並且都成功了。但下一位d a,所以我們需要重新在s中...
KMP學習筆記
最近在搞這個東西,不知道為啥,看一遍sb一遍。終於在今天下午從宿舍裡猛的一起,狂奔到機房中,還在懵逼狀態下的我終於搞懂了這個演算法。縱觀全網,kmp雖然是個很老很經典的演算法,部落格關於它的講解也不少,我就把我的理解寫一遍,希望對大家有所幫助。首先kmp這個東西是幹啥使的呢?比如你在打亡者農藥,你方...
學習筆記 KMP演算法
kmp演算法是一種可以在 o n m 的時間複雜度內實現兩個字串匹配的演算法。acwing 831.kmp字串 給定乙個模式串s,以及乙個模板串p,所有字串中只包含大小寫英文本母以及阿拉伯數字。模板串p在模式串s中多次作為子串出現。求出模板串p在模式串s中所有出現的位置的起始下標。輸入格式 第一行輸...