乙個節點表示乙個回文串。
tot:節點個數,即不同回文串的個數。兩棵樹,節點為0,1,所以最後計數時從2開始
n:新增的字元個數
last:新新增乙個字母後所形成的最長回文串表示的節點
nxt[i][c]:節點i表示的回文串在兩邊新增字元c後變成的回文串編號(兒子)
cnt[i]:節點i表示的本質不同的串的個數,即回文串i的個數(建樹時求出的不是完全的,最後重新統計一遍以後才是正確的)。
len[i]:節點i表示的回文串的長度
fail[i]:節點i失配以後跳轉不等於自身的節點i表示的回文串的最長字尾回文串。
s[i]:第i次新增的字元,開始s[0]=-1
id[i]:記錄節點i表示的回文串的最後乙個字元是第幾個插入的
struct palindromic_tree
void init()
int get_fail(int x)
void add(int c)
last = nxt[cur][c];
cnt[last]++, id[last] = n;
}ll count()
return 0;
}} pam;
theme:給定字串s,求s的所有回文串h出現的次數與長度之積的最大值。
solution:回文樹。就是板子的cnt[i]*len[i]最大值
//theme:給定字串s,求s的所有回文串h出現的次數與長度之積的最大值。
#includeusing namespace std;
#define pb(x) push_back(x)
#define far(i,t,n) for(int i=t;i= 0; i--) cnt[fail[i]] += cnt[i];
for (int i = 2; i < tot; i++)
return ans;
}} pam;
int main()
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const ull hash2 = 50331653;
const int n = 300000 + 10;
const int m = 1000 + 10;
const int inf = 0x3f3f3f3f;
const ll mod = 998244353;
ll ret[n];
ull ha[n], pp[n];
ull getha(int l, int r)
bool check(int l, int r)
struct palindromic_tree
void init()
int get_fail(int x)
void add(int c)
last = nxt[cur][c];
cnt[last]++, id[last] = n;
}ll count()
}return 0;
}} pam;
char str[n];
int main()
while (~scanf("%s", str))
for (int i = 1; i < len; i++)
pam.count();
printf("%lld", ret[1]);
for (int i = 2; i <= len; i++)
printf("\n");
}return 0;
}
回文自動機
回文自動機,又叫回文樹,是由俄羅斯人 mikhailrubinchik於2014年夏發明的 這是一種比較新的資料結構,在原文中已有詳細介紹與 實現。回文樹其實不是嚴格的樹形結構,因為它有是兩棵樹,分別是偶數長度的回文樹和奇數長度的回文樹,樹中每個節點代表乙個回文串。為了方便,第一棵樹的根是乙個長度為...
回文自動機
小小總結 別忘了寫上初始化!當字串下標從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 ...