例題引入:洛谷p3649
話說馬上就要apio了,litble去看了看歷年的apio題……發現這道題用回文樹非常好做,所以就去學了一下回文樹。
所謂回文樹,就是每個節點代表乙個不同的回文串的一種資料結構。
它也有可以模擬於ac自動機的fail指標,表示失配了之後去尋找哪個節點。
此外,每個節點上還要記錄
len:該節點代表的回文串長度
cnt:該節點代表的回文串在原串中出現的次數(然而在建立的過程中這個求不完全,還要再跑一遍count函式去求,這就是後話了)
為了輔助匹配,再弄乙個s,表示當前插入到回文樹里的字元。s0
=−1 s0=
−1
(乙個不可能出現的字元)
一開始回文樹上有兩個節點,0和1。0是輔助處理偶數回文串的,1是輔助處理奇數回文串的。fa
il(0
)=1 fai
l(0)
=1
,因為顯然乙個新加的字元不能去組成乙個長度為2偶數回文串,還可以組成乙個長度為1的奇數回文串。le
n(1)
=−1,
len(
0)=0
l en
(1)=
−1,l
en(0
)=
0,因為每一次新增的新節點的len顯然是其父節點+2,所以奇數回文串要事先減1。
void init() //sz:回文樹節點個數
我們加入了乙個字元x,需要尋找加入這個字元後可以形成的新回文串,這個回文串應該長這樣:
x某乙個原本存在的回文串x
因此匹配方式如下:
int find(int x)
記last為上一次插入後對應的節點,也就是以上乙個插入的字元結尾的最長回文串代表的節點。
首先順著last的fail指標找乙個匹配了了的節點。
然後xjb操作一通,方法如下(應該能看懂……吧?)
void add(int t)
last=ne[cur][t],++cnt[last];
}
也就是傳說中的count函式啦!我們可以把cnt完善一下:
ll count()
return re;
}
最後獲得該題的完整**:
#include
using
namespace
std;
const
int n=300005;
#define ri register int
typedef
long
long ll;
struct orzabs
int find(int x)
void add(int t)
last=ne[cur][t],++cnt[last];
}ll count()
return re;
}}t;char s[n];int slen;
int main()
ural1960 palindromes and super abilities
bzoj2160 拉拉隊排練
bzoj2565 最長雙回文串
回文樹(回文自動機) 筆記
回文樹詳解1 what is palindromic auto machine?回文自動機,又叫回文樹,是由俄羅斯人 mikhailrubinchik於2014年夏發明的 這是一種比較新的資料結構,在原文中已有詳細介紹與 實現。回文樹其實不是嚴格的樹形結構,因為它有是兩棵樹,分別是偶數長度的回文樹和...
回文自動機
回文自動機,又叫回文樹,是由俄羅斯人 mikhailrubinchik於2014年夏發明的 這是一種比較新的資料結構,在原文中已有詳細介紹與 實現。回文樹其實不是嚴格的樹形結構,因為它有是兩棵樹,分別是偶數長度的回文樹和奇數長度的回文樹,樹中每個節點代表乙個回文串。為了方便,第一棵樹的根是乙個長度為...
回文自動機
乙個節點表示乙個回文串。tot 節點個數,即不同回文串的個數。兩棵樹,節點為0,1,所以最後計數時從2開始 n 新增的字元個數 last 新新增乙個字母後所形成的最長回文串表示的節點 nxt i c 節點i表示的回文串在兩邊新增字元c後變成的回文串編號 兒子 cnt i 節點i表示的本質不同的串的個...