詳細揭秘 ACAM
首先明確 ACAM 處理的是多模式串單文字串問題。
先對所有模式串建 trie。然後對於每個點 \(u\) 維護 \(fail_u\) 指標指向 trie 中最長的且是 \(u\) 的字尾的節點。
對於模式串為 he
,hers
,she
,i
,his
建出的 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 向上爬到根都會經過這個模式串節點)。