#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; fail[1]=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; }