「學習筆記」迴文樹/迴文自動機(Palindromic Tree)
引入
有時候題目要求一些這樣的問題
1. 求以串
本質不同的迴文串個數(即長度不同或長度相同且至少有一個字元不相同的字串)
2. 求以位置
結尾的迴文串個數。
這時候使用Manacher顯然有點力不從心,我們可以使用一種比較新穎的字串處理工具迴文樹(Palindromic Tree)。
迴文樹的結構
迴文樹其實是由兩棵樹組成的森林,第一棵樹的根節點是
每個節點儲存以下資訊:
- 表示當前節點失配以後可能匹配的最長迴文串(即當前節點的最長迴文字尾),特別的 ,
- 表示當前節點的孩子,其中 表示在當前字串前後接上字元 所形成的新迴文串。
示例:下圖是字串 的迴文樹(實線表示 ,虛線表示 )
其實就是論文1裡的圖啦
不難看出
的子樹儲存的都是奇數長度的迴文串,而
的子樹中儲存的都是偶數長度的迴文串。
迴文樹的構造
迴文樹的構造採用增量構造。
假設我們已經構造串
的迴文樹。現在要求出在
後新增字元
的迴文樹。
定理:以新加入的字元為結尾的,且未在 中出現的迴文字串最多有 個,且必為新串的最長迴文字尾。
所以只需要求出新串的最長迴文字尾即可。不妨設原串 的最長迴文字尾為 ,那麼只要 ,則新串的最長迴文字尾一定為 ,否則轉移到 ,繼續之前的操作。
如果新串的最長迴文字尾沒有在迴文樹中,則新建一個節點並找出它的 ,方法同上面類似。
迴文樹的複雜度
可以證明一個串 本質不同的迴文串不超過 個,所以狀態數為 。
而通過勢能分析可以證明前文所述的方法時間複雜度為 (使用平衡樹或c++中的map表示 )或 (使用陣列表示 )。其中 為字符集大小。
迴文樹的一些擴充套件
- 從前端插入([HDU5241]Victor and String)
- 前後端插入,刪除字元
- 可持久化迴文樹
老實說,除了第一個我都不會我還是太菜了。但論文裡有詳細講解。
模板題
[APIO2014]Palindrome
Description
考慮一個只包含小寫字母的字串 ,定義一個迴文串的出現值為 在 中的出現次數與其長度的乘積。求 的所有迴文字串中的最大出現值。
Solution
首先建出 的迴文樹,定義