回文樹學習小記

2021-07-09 20:52:05 字數 2545 閱讀 8535

回文樹,顧名思義,用回文串構成的一棵樹,結合了一點ac自動機的思想,打起來不長,用起來挺方便。

變數

首先滿足ac自動機的結構。

定義集合tree:

fail (指向該節點表示的回文串最長回文字尾在樹中的節點,如abbba就是ababbabbba的最長回文字尾)。

son[26] (表示在當前節點表示的回文串兩邊都加上乙個'a'...'z'構成的回文串在樹中的節點是什麼)。

len (表示當前節點表示的回文串的長度)。

sum (表示整個串中節點表示的回文串出現多少次

tree[i].fail,tree[i].son[j],tree[i].len,tree[i],sum

定義last。當前加入第i個字元,last為1...i-1的串的最長回文字尾所在樹中的節點。

定義tot為現在回文樹中最後乙個節點是什麼。

建樹
兩個初始節點0和1,0(分為根節點為0和1的兩棵樹),0的樹都是長度是偶數的字串,1的樹都是長度為奇數的字串 ,0節點一開始的長度len為0,在兩邊加入同樣的字元後長度就為2了,所以之後都為偶數;同理,1節點一開始的長度為-1,在兩邊加入同樣的字元就是長度+2,之後長度就為1了,之後都為奇數,這個len設為-1不僅是為了上面的說法,更是為了方便計算,也可以想象為是開始就少了乙個字元。0的fail是1,因為如果有字串的最長回文字尾是0,那麼這個長度就為1,自己無法指向自己,所以所以就指向0,當時0代表的是偶數,所以還要向奇數的根節點連一條變(本來兩者可以互不相連),讓它轉移到奇數那去,也可以想為0旁邊並沒有少字元,這樣做免去了特判。1不用連,他的初始值為零,但因為len=-1,省去了特判,後面再講。

每次加入乙個字元,判斷s[i]是否等於s[i-tree[last].len-1],否則last=tree[last].fail。因為現在要求的是加進乙個字元後的最長回文字尾,所以要判斷上乙個最長回文字尾的前乙個是否等於s[i],否則沿著最長回文字尾鏈走,知道找到乙個字串符合s[i]as[i]為止,a可以為空串(偶數),少乙個字元(-1奇數),這也是為什麼0要重新連向1de原因,因為連向0的必定是長度為1的奇數串。但是當last跳到1節點時(從0才能到1,最長回文子串就是自己),是否特判。不用!因為tree[1].len=-1,s[i-(-1)-1]=s[i],剛好處理出這個問題。為什麼有最長回文字尾鏈可以走(新的a也應該是1..i-1的字串的字尾,為什麼一次會處理出多個字尾?),實際上因為已經處理出了回文串,所以前面的回文串可以對稱過來,對稱之後末尾剛好也是i-1的加入有這樣的,那就有最長回文字尾鏈走(有點抽象),如圖(a):s是整個串,p是1..i-1的字串,t是它的最長回文字尾,x是s[i],xbx是xax的最長回文字尾。為什麼會有那麼多字尾是以i-1結尾的,但是都已經處理過了。下一層的字串的確是上一層的最長回文字尾,但是沒有在i-1的點就全處理完,由於t是回文串,t下面的完全可以對稱過去,在前面處理完,可能加了x的還沒處理。現在加了乙個x之後,在回文樹中加入新的節點,更新len,son,fail。如果要更新fail,就繼續沿著最長回文字尾鏈走就可以了,因為想xbx是xax的字尾,對稱過去,一定處理過。

manachar行的回文樹幾乎都行

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

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

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

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

【apio2014】回文串(palindrome)

考慮乙個只包含小寫拉丁字母的符串 s。我們定義 s的乙個子串 t的「出現值」為 t在 s中的出現次數乘以t的長度。 請你求出s的所有 回文子串中的最大出現值。

#include

#include

#include

#include

#include

#define fo(i,a,b) for(i=a;i<=b;i++)

#define fod(i,a,b) for(i=a;i>=b;i--)

#define ll long long

using namespace std;

const int maxn=300005;

int i,k,l,t,n,m,tot,last,tasl;

char s[maxn];

struct palindromic_treetree[maxn*2];

ll ans,j;

int main()

last=tree[last].son[s[i]-'a'];

tree[last].sum++;

}fod(i,tot,0)

printf("%lld\n",ans);

}

滅絕樹學習小記

tags 圖論 聽這名字特別酷對吧 不像乙個noip滾粗選手能學的東西 所以只能當乙個搬運工了 orzlitble 滅絕樹和支配樹應該是一種東西 用於 o n m logn 或者 o n m alpha 求解一類如下問題 在一張捕食圖上 從捕食者向 食者有連邊 若某生物的所有食物都滅絕了,則該生物滅...

回文樹學習小結

最近突然撿起了好久不搞的字串,研究了一下一直覺得很神奇的回文樹。相比於manacher,回文樹要顯得強大的多,同樣是接近o n 的複雜度,回文樹只需要多一點的空間,就可以實現許多用manacher實現起來非常複雜的功能。並且就 量而言,回文樹也足夠的簡短,作為處理回文串的工具,實在是非常的美妙。做了...

伸展樹splay學習小記

splay是基本操作,rotate是splay的基本操作。splay now,root 把now splay到root的下面。單旋和雙旋就不說了。我們可以簡化操作,如果是一字型 方向相同 則先旋father,否則先旋now。然後再旋now。rotate now是指將now繞father rotate...