# 【bzoj3160】万径人踪灭 【FFT 卷积】

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=530005,mod=1000000007;
const double pi=3.141592653589793;
int len,n,m,rev[N],f[N],bin[N],p[N];
long long ans;
char str[N],s[N];
struct complex{
double x,y;
complex(){x=y=0;}
complex(double x,double y):x(x),y(y){}
friend complex operator + (const complex &a,const complex &b){
return complex(a.x+b.x,a.y+b.y);
}
friend complex operator - (const complex &a,const complex &b){
return complex(a.x-b.x,a.y-b.y);
}
friend complex operator * (const complex &a,const complex &b){
return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
}a[N],b[N];
void fft(complex *a,int dft){
for(int i=0;i<=n;i++){
if(i<rev[i]){
swap(a[i],a[rev[i]]);
}
}
for(int i=1;i<n;i<<=1){
complex wn=complex(cos(pi/i),dft*sin(pi/i));
for(int j=0;j<n;j+=i<<1){
complex w=complex(1,0);
for(int k=j;k<j+i;k++,w=w*wn){
complex x=a[k];
complex y=w*a[k+i];
a[k]=x+y;
a[k+i]=x-y;
}
}
}
if(dft==-1){
for(int i=0;i<=n;i++){
a[i].x/=n;
}
}
}
void manacher(){
p[0]=1;
int maxr=0,pos=0;
for(int i=1;i<=m;i++){
p[i]=i<maxr?min(p[2*pos-i],maxr-i):1;
while(i-p[i]>=0&&i+p[i]<=m&&s[i-p[i]]==s[i+p[i]]){
p[i]++;
}
if(i+p[i]>maxr){
pos=i;
maxr=i+p[i];
}
}
}
int main(){
bin[0]=1;
for(int i=1;i<N;i++){
bin[i]=2*bin[i-1]%mod;
}
scanf("%s",str+1);
len=n=strlen(str+1);
s[0]='#';
for(int i=1;i<=n;i++){
s[++m]=str[i];
s[++m]='#';
}
for(int i=0;i<=m;i++){
if(s[i]=='a'){
a[i].x=1;
}else if(s[i]=='b'){
b[i].x=1;
}
}
m*=2;
for(n=1;n<=m;n<<=1);
for(int i=0;i<=n;i++){
rev[i]=(rev[i>>1]>>1)|((i&1)*(n>>1));
}
fft(a,1);
for(int i=0;i<=n;i++){
a[i]=a[i]*a[i];
}
fft(a,-1);
fft(b,1);
for(int i=0;i<=n;i++){
b[i]=b[i]*b[i];
}
fft(b,-1);
m/=2;
manacher();
for(int i=1;i<=m;i++){
f[i]=int(a[i<<1].x+0.5)+int(b[i<<1].x+0.5);
f[i]=(f[i]+1)/2;
ans=ans+bin[f[i]]-1-p[i]/2;
ans=(ans+mod)%mod;
}
printf("%lld\n",ans);
return 0;
}
posted @ 2018-04-15 10:31  ez_2016gdgzoi471  阅读(72)  评论(0编辑  收藏  举报