yang-xi-jie-mi-acam

iorit發表於2024-03-07

詳細揭秘 ACAM

首先明確 ACAM 處理的是多模式串單文字串問題。

先對所有模式串建 trie。然後對於每個點 \(u\) 維護 \(fail_u\) 指標指向 trie 中最長的且是 \(u\) 的字尾的節點。

對於模式串為 heherssheihis 建出的 ACAM 如下

和 KMP 類似地,我們在匹配文字串時如果下一個字元沒有對應的轉移邊,我們需要透過跳 \(fail\) 來找下一個節點。(類似 \(nxt\)

例如文字串為 shers,我們跑到節點 \(9\) 後沒有找到 r 的邊,那麼跳 \(fail\) 後就可以找到 r 邊。

也就是說,走到結點 \(9\) 後如果想要找 r 的轉移應當不斷跳 fail 鏈直到找到 r 邊。

那麼我們為了簡化程式碼,我們直接將 \(9\) 節點的 r 轉移邊指向 \(3\)

最後建出的 ACAM 如下。黑色是為了程式碼好寫而新加的邊。

現在你學會 ACAM 加強版 了。可是 ACAM 二次加強版 每次暴力跳 fail 會 TLE。

考慮文字串每個字首分別跳 fail 得到的節點,這些點就是在文字串中出現過的字串。

我們把這些點打上標記,那麼最後每個模式串的答案就是所在節點的標記數量。

現在我們要支援 fail 樹上的到根路徑加,單點查詢。這個可以用資料結構維護,但是也有更方便的辦法:

把每個文字串節點打上 tag,最後 pushup 統計模式串節點的 fail 子樹內有多少 tag(因為每個 tag 向上爬到根都會經過這個模式串節點)。