#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
struct PT{
//回文树中每个节点表示一个回文串,所以有偶数长度的树和奇数长度的树两棵
//next指针 next[u][i]表示u节点左右添加字符i之后得到的回文串节点
int next[N][26];
//fail指针 失配后跳转到最长后缀回文串对应的节点
int fail[N];
//节点对应回文串在原串中出现次数
int cnt[N];
//num[i]表示以节点i所表示的回文串右端点结尾的回文串个数(包括自身),即fail指针的深度
int num[N];
//节点对应回文串的长度
int len[N];
//存放添加的字符
int S[N];
//上一个字符所在节点
int last;
//字符数,不等于节点数
int n;
//回文树总结点数,包括奇偶两个空节点,节点编号为0到p-1
int p;
//初始化
void init(){
p=0;
//奇偶空节点
newnode(-1);
newnode(0);
last=0;
n=0;
S[n]=-1;
//偶数根的fail指针是奇数根,奇数根的fail指针是本身
fail[0]=1;
}
//创建长度为l的新节点
int newnode(int l){
for(int i=0;i<26;i++){
next[p][i]=0;
}
cnt[p]=0;
num[p]=0;
len[p]=l;
return p++;
}
//找到新插入字符c的回文匹配位置
int getFail(int x){
//在节点x对应串的后面加上一个字符,就判断x前面字符是否相同
//若相同直接构成新的回文串,不同就跳到fail,即最长回文后缀
//S[n-len[x]-1]就是新加的字符(S[n])关于x串的对称字符
while(S[n-len[x]-1]!=S[n]){
x=fail[x];
}
return x;
}
//插入字符c
void add(int c){
c-='a';
S[++n]=c;
//通过上一个回文串位置找到当前回文串匹配位置,也就是当前回文串节点的父节点
int cur=getFail(last);
if(!next[cur][c]){
//出现了一个新的本质不同的回文串
int now=newnode(len[cur]+2);
//类似于AC自动机,往上跳直到找到满足条件的串节点
fail[now]=next[getFail(fail[cur])][c];
//fail指针深度加1
num[now]=num[fail[now]]+1;
}
//最新回文串节点
last=next[cur][c];
cnt[last]++;
}
//统计每个节点回文串出现次数
void count(){
//从子节点逆推
for(int i=p-1;i>=0;i--){
//i节点出现,说明其最长回文后缀fail[i]也出现
cnt[fail[i]]+=cnt[i];
}
}
}ac;
int main(void){
return 0;
}