回文樹詳解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...