回文自動機

2021-08-27 05:21:34 字數 2337 閱讀 7228

回文自動機,又叫回文樹,是由俄羅斯人 mikhailrubinchik於2023年夏發明的(

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

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

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

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

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

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

方法的思想和kmp,ac自動機很類似,如果你理解了kmp與ac自動機,那麼這個演算法基本可以一看就懂。

節點0後連的點一定是長度為2的回文串,節點1後連的點一定是長度為1的回文串

先貼一波**

#include #include #include #include #include #include #include #include #include #include #include #include #include #define  ll long long

#define ull unsigned long long

using namespace std;

const int maxn = 100005 ;

const int n = 26 ;

char s[maxn];

struct palindromic_tree

void init() //初始化

int get_fail(int x) //失配後,在回文串x中的所有字尾裡找到乙個串右端+s[n]依然構成回文串

void add(int c,int pos) //cur,last,now都代表乙個字串,而不是乙個下標/字元

last = next[cur][c] ;

cnt[last] ++ ;

putchar(10);

}void count()

} run;

int main()

{ scanf("%s",&s);

int n=strlen(s);

run.init();

for(int i=0; i看其他部落格講的,都看不懂,可能是自己太笨了...

所以就直接拿**來啃,終於理解這個演算法的原理。

回文自動機,其實關鍵是理解fail,基礎就是我上面說的那句話————回文自動機的節點表示的是乙個回文串!!!

然後難點就是fail[now] = next[get_fail(fail[cur])][c] ; 這句**

首先定義字尾回文串:字串的乙個字尾(不包括字串本身),該字尾是回文串

//因為這裡now='c'+cur+'c'已經代表了以'c'結尾的最長的回文串,那麼如果這個匹配失敗,我們

需要找到fail[now]='c'+w+'c'——以'c'結尾的次長的回文串,該回文串的乙個性質——

該回文串fail[now]是now的最長回文串字尾,因為這樣我們才能保證在now匹配失敗後,

fail[now]能立即被匹配,不需要任何移動。這一步就可以借助fail[cur]來完成

例如bbabba 

最後乙個字元'a'的最長回文now是"abba",

cur="bb",fail[cur]="b",然後在fail[cur]中沒有找到滿足條件的解,

一直搜到x=0,表示長度為2的回文串,len[x]=1,發現還是不對,

然後x=fail[0]=1,長度為1的回文串,len[x]=-1,發現就是他本身

那麼他的fail[now]="a"

abbaabba

最後乙個字元'a'的now是"abbaabba",

cur="bbaabb",fail[cur]="bb"

他的fail[now]="abba"

然後next[get_fail(fail[cur])][c] 非空的原因見圖

看完這個還不懂得可以去看一下貼在上面原來大牛的部落格

最後貼一波他的功能

1.求串s字首0~i內本質不同回文串的個數(兩個串長度不同或者長度相同且至少有乙個字元不同便是本質不同)

2.求串s內每乙個本質不同回文串出現的次數

3.求串s內回文串的個數(其實就是1和2結合起來)

4.求以下標i結尾的回文串的個數

回文自動機

乙個節點表示乙個回文串。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...

回文自動機

回文樹 回文自動機 他的功能如下 求字首字串中的本質不同的回文串種類 求每個本質不同回文串的個數 以下標每個本質不同回文串包含的本質不同回文串種類 fail fail指標,類似於ac自動機,返回失配後與當前cnt 在最後統計後它可以表示形如以 num 表示以 len 表示以 s 存放新增的字元 n ...