回文樹(回文自動機) 筆記

2021-10-02 22:26:48 字數 2701 閱讀 3773

回文樹詳解1:what is palindromic auto-machine?:回文自動機,又叫回文樹,是由俄羅斯人 mikhailrubinchik於2023年夏發明的(

這是一種比較新的資料結構,在原文中已有詳細介紹與**實現。

回文樹其實不是嚴格的樹形結構,因為它有是兩棵樹,分別是偶數長度的回文樹和奇數長度的回文樹,樹中每個節點代表乙個回文串。

為了方便,第一棵樹的根是乙個長度為0的串,第二棵就是為-1的串,不要感到奇怪,就是-1。

可以證明,最多只有n個結點(n是串的長度)。這個可以用manacher演算法來證明。

如果某結點代表的是串ccabacc,那麼它的父親代表的串就是去掉前後兩個字元cabac。

每個點還有乙個fail指標,表示這個串的字尾中最長的回文串,比如babab的fail指向bab,bab的指向b。

方法的思想和kmp,ac自動機很類似

回文樹詳解2:回文樹介紹(palindromic tree)

題解 p5496 【【模板】回文自動機(pam)】:裡面有fail陣列的含**釋,和,借助trans陣列解雙倍回文

首先,如上面說到的,樹中每個節點代表乙個回文串,那麼由字串「abbaabba」得到的回文樹結構大概是這個樣子:(紅色是結點編號,節點裡面是 結點所代表的的回文串 及其長度)

1、計算本質不同的回文串個數

像ac自動機一樣,我們需要通過乙個陣列next[ ][ ]來存回文樹的結構。next[i][j]表示在結點i表示的回文串前後加乙個字元『j』得到的新的回文串編號

每個點的fail指標,表示它的字尾中最長的回文串的編號。實際上我們可以通過fail陣列遍歷到以這個點結尾的所有的字尾回文串。知道這一點,我們就可以計算串s內回文串的個數了

我們用乙個last記錄以上乙個結點結尾的最長回文串的編號,當我們新加入乙個結點時,我們就可以通過上乙個結點的fail找到以當前結點結尾的最長回文串,然後判斷這個回文串是否已經存在,不存在就新建乙個結點來存它。然後繼續遍歷上乙個結點的fail找到當前結點的fail(這段的詳細說明可以看上面詳解2中回文串構造部分)

//剛看完回文樹的時候一直有點迷為什麼只用找一次fail就可以知道以當前結點結尾的所有回文串的資訊,還有為什麼加入結點的過程中cnt陣列記錄的次數是不完整的,所以過了幾天才來補這篇部落格hhh。//如下圖1,紅色表示的回文串是這個最長回文串的fail,即它的最長字尾回文串,實際上如圖2這個回文串的資訊在前面已經處理過了,所以我們只用將fail「指標」指向這個回文串,就可以遍歷到所有字尾回文串了

明白這些,我們就可以解決最基本的問題:計算字串中本質不同的回文串個數,也就是回文樹結點個數p減去兩個根結點——p-2

struct pal_tree

void

init()

//初始化

intgetfail

(int x)

//和kmp一樣,失配後找乙個盡量最長的

void

add(

int c)

last=net[cur]

[c];

//cnt[last]++;

}}tree;

intmain()

//部分注釋來自回文串詳解1

2、計算串s內回文串的個數

既然我們可以通過fail陣列遍歷到以這個點結尾的所有的字尾回文串,那麼就可以用乙個陣列num[ ]記錄每個結點的fail陣列的「深度」,這個「深度」也就是以這個結點結尾的回文串個數

3、計算串s內每乙個本質不同回文串出現的次數

類似tire樹中的vs陣列,cnt陣列只是將「以當前結點結尾的最長回文串」出現的次數上+1了,見上文**中倒數第三行的注釋。所以它的fail鏈前面的結點,即以當前結點結尾的其他回文串還沒有統計,所以最後還要處理一遍cnt陣列:

void

ccount()

4、整體實現
#include

#include

#include

#include

#include

#include

using namespace std;

#define int long long

const

int manx=

3e5+10;

const

int max_len=

2e6+10;

char s[manx]

;int ans=0;

struct pal_tree

void

init()

intgetfail

(int x)

void

add(

int c)

last=net[cur]

[c];

cnt[last]++;

//新增3

}void

ccount()

//新增4

}}tree;

signed

main()

回文自動機

回文自動機,又叫回文樹,是由俄羅斯人 mikhailrubinchik於2014年夏發明的 這是一種比較新的資料結構,在原文中已有詳細介紹與 實現。回文樹其實不是嚴格的樹形結構,因為它有是兩棵樹,分別是偶數長度的回文樹和奇數長度的回文樹,樹中每個節點代表乙個回文串。為了方便,第一棵樹的根是乙個長度為...

回文自動機

乙個節點表示乙個回文串。tot 節點個數,即不同回文串的個數。兩棵樹,節點為0,1,所以最後計數時從2開始 n 新增的字元個數 last 新新增乙個字母後所形成的最長回文串表示的節點 nxt i c 節點i表示的回文串在兩邊新增字元c後變成的回文串編號 兒子 cnt i 節點i表示的本質不同的串的個...

回文自動機

小小總結 別忘了寫上初始化!當字串下標從0 00開始時,pos pospo s初始化為 1 1 1 若從1 11開始,則pos pospo s初始化為0 00 最終的pos pospo s代表最後乙個字元的下標 前者為n 1 n 1n 1,後者為n nn 根據本質不同的回文子串數量不超過 s s s...