這題建立一棵迴文樹,然後用dfs搜索答案,但是有一點需要注意,就是打vis的標記時,如果標記爲1,那麼在好幾個節點都對同一個字符i打過標記,此時的搜索從字符i點回溯,回到它的父親節點,搜索其它的字符,回溯的時候把vis[i]標記成0了,之前的vis[i]標記全被清空了,如果該父親的其它字符節點下,有字符i的孩子,則此時統計就會出錯。所以打vis標記的時候讓vis++,而不是標記爲0。
#include <iostream>
#include <stdio.h>
using namespace std;
const int MAXN=3e5+10;
const int N=26;
char str[MAXN];
struct PAM {
int len[MAXN];
int num[MAXN];
int s[MAXN];
int fail[MAXN];
int next[MAXN][N];
int cnt[MAXN];
int last,p,n;
int newNode(int l) {
for (int i=0;i<N;i++) next[p][i]=0;
cnt[p]=0;
num[p]=0;
len[p]=l;
return p++;
}
void init() {
n=0;
p=0;
last=0;
newNode(0);
newNode(-1);
fail[0]=1;
s[0]=-1;
}
int getFail(int x) {
while (s[n-len[x]-1]!=s[n]) x=fail[x];
return x;
}
void add(int c) {
c-='a';
s[++n]=c;
int cur=getFail(last);
if (!next[cur][c]) {
int now=newNode(len[cur]+2);
fail[now]=next[getFail(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];
}
}
}pt;
int vis[N];
long long ans=0;
void dfs(int x,int cnt)
{
ans+=cnt*pt.cnt[x];
for (int i=0;i<N;i++) {
if (pt.next[x][i]) {
if (!vis[i]) {
vis[i]++;
dfs(pt.next[x][i],cnt+1);
vis[i]--;
}
else {
dfs(pt.next[x][i],cnt);
}
}
}
}
int main()
{
pt.init();
scanf("%s",str);
for (int i=0;str[i];i++) {
pt.add(str[i]);
}
pt.count();
// printf("%d\n",pt.cnt[0]);
dfs(0,0);
dfs(1,0);
printf("%lld\n",ans);
return 0;
}