KMP 和 AC 自動機(坑)

2021-09-24 14:25:24 字數 1921 閱讀 9263

xyynb!

kmp這裡,字串從1開始計數

眾所周知,kmp是一種單串匹配演算法,把樸素演算法的o(|s|*|t|)優化到了o(|s|+|t|)

如上圖,在進行樸素演算法時,如果我們已經進行了一些匹配成功,實際上我們就知道了原串的一些資訊,理論上就可以使用這個資訊來加速匹配,跳過一些絕對不可能匹配成功的情況。

所以,該怎麼做呢?這就是kmp很迷的地方之一,也是我一直看不懂kmp的乙個點。

為此,xyy提到了border的概念。border即是某個字串的最長相等前字尾(不包含自己)。

有了這個定義,再結合上面的圖,就可以看到,如果在某個字元失配了,說明這個字元前的模式串t和字串s是相等的,由於border的存在,可以直接跳過一些字串,直接跳到失配字元前的模式串t的border,比較border之後的字元。

一定沒有錯過什麼能夠正確匹配的情況嗎?是的,反證可以證明,要是存在,那border就不是最長了。

也就是說,kmp分為兩個步驟,求t中每個字元前的子串對應的border長度,然後匹配。一般把前者(每個字元前的子串對應的border的長度)定義為fail陣列,或者xyyπ()函式

在t也很長的時候,暴力求解fail陣列也是不可取的。

這種情況下,可以看出:

由於π(3)=1,可得t[1...1]==t[3...3]又由於t[2]==t[4]t[1...2]==t[3...4]所以π(4)=2=π(3)+1

綜上,t[i+1]==t[π(i)+1],則π(i+1)=π(i)+1

那如果t[i+1]≠t[π(i)+1]呢?

有乙個神奇的性質,borderborder仍然是原串的border

由於abacaba是原串的border,則黃串+c+綠串==藍串+c+紅串

由於abaabacababorder,則黃串==綠串,藍串==紅串

所以,黃串==綠串==藍串==紅串

因此,我們可以用遞迴的方法,如果t[i+1]≠t[π(i)+1],則檢查t[i+1]==t[π(π(i))+1],以此類推,直至出現相等。如果真的很慘,乙個border,那麼應該遞迴到π(i)=0,這時,t[i+1]==0

綜上,求fail陣列的**為:

void getfail()

return;

}

kmp與ac自動機

xj比賽做到一道字串題,結果發現想打個字串匹配都只會n 2了,又一次忘記了kmp 想必是當初學這玩意心理陰影面積太大了。這裡再梳理一遍kmp和ac自動機 以便下次再忘了有地方看.kmp 用於處理對於字串s,想知道它在另外某個串哪些位置出現的問題,先做預處理得到乙個失配陣列,這個陣列第i位表示s的前i...

AC自動機(KMP 字典樹)

ac自動機 kmp 字典樹 題目 輸入n個串,判斷有多少個搜尋串的子串 in out 1 47a ababc abcd abcde abcdef abcdefg abcd includeusing namespace std char str 1000000 100 struct node root...

AC自動機 建立nlogn個AC自動機

string set queries 題意 給你3種操作,1 加入乙個串到集合中。2 刪除集合中的某乙個串 3 查詢集合中的字串在給定的字串種出現幾次。同乙個串可重複 解法 建立多個ac自動機,用二進位制分組來處理。加入給你21個串 分為 16 4 1,再新增乙個串的時候,即21 1,22 16 4...