哦也!偉大的回文樹(回文自動機)!

2021-08-19 12:54:16 字數 1748 閱讀 8551

例題引入:洛谷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表示的本質不同的串的個...