其实我就是来贴一个FFT的版,然后就是回文树记着先把儿子的信息更新好再把父亲的指针指下来
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<complex>
#define maxn 400021
#define Mod 1000000007
using namespace std;
int ans[maxn],er[maxn];
struct cp{
double x,i;
cp(double a=0,double b=0):x(a),i(b){}
cp operator+(const cp& b){return cp(x+b.x,i+b.i);}
cp operator-(const cp& b){return cp(x-b.x,i-b.i);}
cp operator*(const cp& b){return cp(x*b.x-i*b.i,x*b.i+i*b.x);}
}a[maxn],b[maxn];
int rev[maxn],t;
void fft(cp *a,int n,int f){
for(int i=0;i<n;i++)if(rev[i]>i)swap(a[i],a[rev[i]]);
for(int j=1;j<n;j<<=1){
cp wn(cos(M_PI/j),f*sin(M_PI/j));
for(int i=0;i<n;i+=(j<<1)){
cp t0,t1,w0(1,0);
for(int k=0;k<j;k++,w0=w0*wn){
t0=a[k+i];t1=w0*a[k+i+j];
a[k+i]=t0+t1,a[k+i+j]=t0-t1;
}
}
}
}
void solve(cp *a,int n,int* rmp){
fft(a,n,1);
for(int i=0;i<n;i++)a[i]=a[i]*a[i];
fft(a,n,-1);
for(int i=0;i<n;i++)rmp[i+1]+=(int)(a[i].x/n+0.5);
}
struct Tree{
int tot,ch[maxn][2],last,len[maxn],fail[maxn],s[maxn],n;
int cnt[maxn];
void init(){tot=1;len[1]=-1;fail[0]=1;s[0]=-1;}
int get_fail(int x){
while(s[n]!=s[n-len[x]-1])
x=fail[x];
return x;
}
void insert(int x){
s[++n]=x;
int cur=get_fail(last);
if(!ch[cur][x]){
len[++tot]=len[cur]+2;
fail[tot]=ch[get_fail(fail[cur])][x];
ch[cur][x]=tot;
}
cnt[last=ch[cur][x]]++;
}
int count(){
int ans=0;
for(int i=tot;i>1;i--)cnt[fail[i]]+=cnt[i];
for(int i=2;i<=tot;i++)ans=(ans+cnt[i])%Mod;
return ans;
}
}T;
char s[maxn];
int main(){
int n,len=0,Ans=0;
scanf("%s",s);n=strlen(s);
for(int i=0;i<n;i++){
if(s[i]=='a')a[i]=cp(1,0);
else b[i]=cp(1,0);
}
for(t=1;t<2*n;t<<=1)len++;
for(int i=0;i<=t;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<len-1);
solve(a,t,ans);solve(b,t,ans);
er[0]=1;for(int i=1;i<=n*2;i++)er[i]=er[i-1]*2%Mod;
for(int i=0;i<2*n;i++)Ans=(Ans+er[ans[i]+1>>1]-1)%Mod;
T.init();
for(int i=0;i<n;i++)T.insert(s[i]-'a');
Ans=(Ans+Mod-T.count())%Mod;
cout<<Ans;
return 0;
}