一篇很好的回文树学习博客
模板题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5+100;
char str[N];
struct Palindromic_Tree {
// 每一个节点表示一个回文串
int s[N];
int next[N][26];//next指针,next[i][j] 表示在串 i 前后加字母 c ,形成当前的回文串
int fail[N]; //fail指针,失配后跳转到fail指针指向的节点
int cnt[N]; // 表示节点i表示的本质不同的串的个数 (建树时求出的不是完全的,最后count()函数跑一遍以后才是正确的)
int num[N]; // 表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数。??
int len[N]; // len[i] 表示节点i表示的回文串的长度
int p, n, last; // 节点指针,字符数组指针,last指针 ( 指向上一个字符所在的节点 )
int newnode(int l){// 新建节点
for(int i = 0; i < 26; i++)
next[p][i] = 0;
cnt[p] = num[p] = 0;
len[p] = l;
return p ++;
}
void init(){
p = 0;
newnode(0);
newnode(-1);
s[0] = -1;
fail[0] = 1;
n = 0; last = 0;
}
int getfail(int x){
while( s[n-len[x]-1] != s[n] )// 配后找一个尽量最长的
x = fail[x];
return x;
}
void add(char c){
c -= 'a';
s[++n] = c;
int cur = getfail( last );// 通过上一个回文串找这个回文串的匹配位置
if(next[cur][c] == 0){// 如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串
int now = newnode( len[cur]+2 );
fail[now] = next[ getfail(fail[cur]) ][c];// 建立fail指针,以便失配后跳转
next[cur][c] = now;
num[now] = num[fail[now]] + 1;
}
last = next[cur][c];
cnt[last] ++;
}
void count(){
for ( int i = p - 1 ; i >= 0 ; -- i ) cnt[fail[i]] += cnt[i] ;
//父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
}
}pt;
int main(){
cin >> str;
pt.init();
int l = strlen(str);
for(int i = 0; i < l; i++){
pt.add(str[i]);
}
pt.count();
ll ma = 0;
for(int i = 0; i < pt.p; i++){
ma = max(ma, (ll)pt.cnt[i] * pt.len[i]);
}
cout << ma << endl;
return 0;
}