
解题思路:
FFT在处理卷积时可以将自己与自己卷,在某一种字母上标1其他标0,做字符集次就好了。
(回文就是直接对称可以联系偶函数定义理解,根据这个性质就可以将字符串反向实现字符串匹配)。
最后利用容斥回文字符2的次幂-回文串就好了。
回文串计数当然要回文自动机了。
代码:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
const int maxn=;
const double PI=acos(-1.0);
const lnt mod=(lnt)(1e9+);
struct cp{
double x,y;
cp(){};
cp(double a,double b){x=a,y=b;}
cp friend operator + (cp a,cp b){return cp(a.x+b.x,a.y+b.y);}
cp friend operator - (cp a,cp b){return cp(a.x-b.x,a.y-b.y);}
cp friend operator * (cp a,cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
}A[maxn],B[maxn],C[maxn];
struct PAM{
struct pant{
int tranc[];
int len;
int pre;
int wgt;
}h[maxn];
int siz;
int fin;
lnt ans;
bool mis(char *a,int i,int lsp)
{
return a[i]!=a[i-h[lsp].len-];
}
void Insert(char *a,int i)
{
int nwp,lsp,mac;
lsp=fin;
int c=a[i]-'a';
while(mis(a,i,lsp))
lsp=h[lsp].pre;
if(!h[lsp].tranc[c])
{
nwp=++siz;
mac=h[lsp].pre;
h[nwp].len=h[lsp].len+;
while(mis(a,i,mac))
mac=h[mac].pre;
h[nwp].pre=h[mac].tranc[c];
h[lsp].tranc[c]=nwp;
h[nwp].wgt=h[h[nwp].pre].wgt+;
}
fin=h[lsp].tranc[c];
ans+=h[fin].wgt;
return ;
}
PAM(){}
PAM(char *a,int n)
{
ans=;
siz=;
fin=;
h[].pre=h[].pre=;
h[].len=-;
h[].len=;
for(int i=;i<=n;i++)
Insert(a,i);
}
lnt val(void)
{
return ans;
}
};
int lim;
int len;
int n,m;
int pos[maxn];
lnt pow2[maxn];
char str[maxn];
void getpos(void)
{
for(int i=;i<len;i++)
pos[i]=(pos[i>>]>>)|((i&)<<(lim-));
return ;
}
void Fft(cp *a,double flag)
{
for(int i=;i<len;i++)
if(i<pos[i])
std::swap(a[i],a[pos[i]]);
for(int i=;i<=len;i<<=)
{
cp wn(cos(2.00*PI*flag/(double)(i)),sin(2.00*PI*flag/(double)(i)));
for(int j=;j<len;j+=i)
{
cp w(1.00,0.00),t;
for(int k=;k<(i>>);k++,w=w*wn)
{
t=a[k+j+(i>>)]*w;
a[j+k+(i>>)]=a[j+k]-t;
a[j+k]=a[j+k]+t;
}
}
}
return ;
}
int main()
{
scanf("%s",str+);
int lth=strlen(str+);
for(int i=;i<=lth;i++)
if(str[i]=='a')
A[i-].x=1.00;
else
B[i-].x=1.00;
while((<<lim)<(lth<<))
lim++;
len=<<lim;
getpos();
Fft(A,);
Fft(B,);
for(int i=;i<len;i++)
A[i]=A[i]*A[i]+B[i]*B[i];
Fft(A,-);
pow2[]=;
for(int i=;i<=len;i++)
pow2[i]=pow2[i-]*2ll%mod;
lnt ans=;
for(int i=;i<len;i++)
ans=(ans+pow2[((lnt)(A[i].x/(double)(len)+0.5)+1ll)/]-1ll)%mod;
PAM P(str,lth);
ans=((ans-P.val())%mod+mod)%mod;
printf("%lld\n",ans);
return ;
}