回文树模板
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=3e5+4;
struct Palindromic_Tree{
int next[maxn][26];
int fail[maxn];
int cnt[maxn]; //表示每个回文串出现的次数
int num[maxn]; //表示有多少回文串和[i节点表示的回文串]有共同的结尾(i节点回文串包括自己的后缀数)
int len[maxn]; //i节点回文串长度
int s[maxn];
int p; //当前节点指针
int last;
int n; //字符数组指针
int new_node(int l){
for(int i=0;i<26;i++)
next[p][i]=0;
cnt[p]=0;
num[p]=0;
len[p]=l;
return p++;
}
void init(){
p=0;
new_node(0);
new_node(-1);
last=0;
n=0;
s[0]=-1;
fail[0]=1; //偶根的后缀是奇根
}
int get_fail(int x){
while(s[n-len[x]-1]!=s[n])
x=fail[x];
return x;
}
void extend(int c){
c-='a';
s[++n]=c;
int cur=get_fail(last);
if(!next[cur][c]){
int now=new_node(len[cur]+2);
fail[now]=next[get_fail(fail[cur])][c];
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]; //这些在第一次正向计数时没有计数到
}
}
}tree;
char s[maxn];
int main(){
while(cin>>s){
int n=strlen(s);
tree.init();
for(int i=0;i<n;i++){
tree.extend(s[i]);
}
tree.Count();
cout<<(tree.p)-2<<endl;
}
return 0;
}