回文自動機,據說是解決回文問題的利器。
最近剛好遇到一道回文問題,加上正好閒著沒事幹,就來學了學。
感覺板子還是非常簡潔的,容易記憶。
與一般自動機類似,定義乙個節點的資訊。
一般包括表示長度、\(fail\)指標、後繼節點,當然視具體題目還要維護一些特殊資訊。
但也要注意回文自動機與一般自動機的區別,就是它的後繼\(x\)表示在當前串左右兩邊各加上乙個字元\(x\)(要保證每個節點對應的串是回文串)。
考慮回文分為奇回文和偶回文,因此回文自動機乙個特殊的地方就是,它有兩個根:奇根以及偶根。
分別設定它們的初始資訊:
節點編號
表示長度
\(fail\)指標
奇根
\(1\)
\(-1\)
奇根偶根皆可
偶根
\(0\)
\(0\)
奇根回文串和一般的字串相比要相對複雜,因此它的\(fail\)指標也不能和其他自動機一樣直接呼叫,而需要為它寫乙個專門的函式。
首先,乙個節點的\(fail\)指標所指向的,是該回文串的最長回文字尾所對應的節點。
但在具體使用時,由於回文串的後繼節點要求在串兩側各加上乙個字元,因此乙個節點的\(fail\)指標並不一定在任何時候都能實現擴充套件。
因此,我們需要不斷跳\(fail\),直至找到乙個合法的節點,滿足它可以向兩側擴充套件。
這一過程可以定義為乙個函式\(fail(x,id)\),具體實現詳見**。
插入乙個新的位置\(id\),首先我們要通過\(t=fail(lst,id)\)得到第乙個可擴充套件位置。
如果\(t\)已經有對應兒子,就不需要操作了;否則,我們新建乙個節點,節點長度就是\(t\)的長度加\(2\)(最後一次重複,回文串每次在串兩側各加上乙個字元),而\(fail\)指標就是繼續上跳,得到\(fail(fail[t],id)\)。
這一過程是非常簡短,也非常簡單的。
#include#define tp template#define ts template#define reg register
#define ri reg int
#define con const
#define ci con int&
#define i inline
#define w while
#define n 500000
using namespace std;
int n;char s[n+5];
class palindromeautomation
o[n+5];
i int fail(ri x,ci id) //根據實際情況找到合法的節點
public:
i palindromeautomation() //初始化節點資訊
i int ins(ci id)
}p;int main()
初學回文自動機
回文這個東西,有一些不錯的演算法。比如馬拉車演算法,就是一種非常優秀的演算法。我也學過一篇有關馬拉車的文章,非常的簡單易懂。但我們今天講的是比馬拉車更強的演算法 回文自動機。回文自動機和ac自動機有一些類似的地方,所以有興趣的同學可以看這篇文章來了解 ac自動機 好了,在開始今天的正文之前,我們得先...
回文自動機 初學
今天學習了一下回文自動機pam,發現比字尾自動機sam簡單好多啊。clj那個sam的ppt講的我頭昏腦漲的 叫你弱叫你弱 簡單寫一下免得自己忘記。幾個陣列 1.像各種自動機一樣,用ch x c 表示狀態x後新增字母c之後轉移到的狀態。2.同樣,用sum x 表示狀態x所含的回文串的個數 和sam一樣...
回文自動機
回文自動機,又叫回文樹,是由俄羅斯人 mikhailrubinchik於2014年夏發明的 這是一種比較新的資料結構,在原文中已有詳細介紹與 實現。回文樹其實不是嚴格的樹形結構,因為它有是兩棵樹,分別是偶數長度的回文樹和奇數長度的回文樹,樹中每個節點代表乙個回文串。為了方便,第一棵樹的根是乙個長度為...