答案
ans=
a
n
s
=
所有回文子串个数
−
−
连续的回文子串个数
现在这两个分别考虑
以为对称轴的对称字符个数
f(i)=∑j=1i(strj==str2∗i−j)
f
(
i
)
=
∑
j
=
1
i
(
s
t
r
j
==
s
t
r
2
∗
i
−
j
)
,那么以
i
i
为对称轴的对称子串个数为
我日这怎么这么像卷积??
将“a”,“b”分别视作1,0
那么
f(i)=∑j=1iaj∗a2∗i−j
f
(
i
)
=
∑
j
=
1
i
a
j
∗
a
2
∗
i
−
j
我日真的是卷积!
FFT一发
后面那个Manacher显然
代码如下:
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define MOD 1000000007
#define N 2000020
using namespace std;
const double DFT=2.0,IDFT=-2.0;
const double pi=acos(-1);
struct Complex{
double x,y;
Complex(double _=0.0,double __=0.0):x(_),y(__){}
Complex operator + (Complex b) {return Complex(x+b.x,y+b.y);}
Complex operator - (Complex b) {return Complex(x-b.x,y-b.y);}
Complex operator * (Complex b) {return Complex(x*b.x-y*b.y,x*b.y+b.x*y);}
}a[N],b[N];
char s[N],str[N];
int n,len,len1,id,mx;
int pos[N],p[N];
long long q[N];
long long ans;
inline void FFT(Complex x[],double mode){
for(int i=0;i<len;i++)
if(i<pos[i])
swap(x[i],x[pos[i]]);
for(int i=2,mid=1;i<=len;i<<=1,mid<<=1){
Complex wm(cos(2.0*pi/i),sin(mode*pi/i));
for(int j=0;j<len;j+=i){
int r=j+mid;
Complex w(1,0);
for(int k=j;k<r;k++,w=w*wm){
Complex y=x[k],z=w*x[k+mid];
x[k]=y+z;x[k+mid]=y-z;
}
}
}
if(mode==IDFT)
for(int i=0;i<len;i++)
x[i].x/=len;
return;
}
inline void solve(char c){
for(int i=0;i<len;i++) a[i]=Complex(0,0);
for(int i=0;i<len;i++)
if(s[i]==c)
a[i].x=1;
FFT(a,DFT);
for(int i=0;i<len;i++)
b[i]=b[i]+a[i]*a[i];
return;
}
inline long long Manacher(){
str[0]='#';
for(int i=0;i<n;i++){
str[i*2+1]=s[i];
str[i*2+2]='#';
}
len1=n*2;
str[++len1]='%';
id=mx=0;
for(int i=0;i<=len1;i++){
if(i<mx) p[i]=min(mx-i,p[id*2-i]);
else p[i]=0;
while(str[i-p[i]-1]==str[i+p[i]+1])
p[i]++;
if(i+p[i]>mx) mx=i+p[i],id=i;
}
long long tmp=0;
for(int i=0;i<len1;i++)
tmp=(tmp+(p[i]+1)/2)%MOD;
return tmp;
}
int main(){
scanf("%s",s);
n=strlen(s);
q[0]=1;
for(int i=1;i<=n;i++) q[i]=q[i-1]*2%MOD;
for(len=1;len<n<<1;len<<=1);
for(int i=0;i<len;i++){
pos[i]=pos[i>>1]>>1;
if(i&1) pos[i]|=len>>1;
}
solve('a');solve('b');
FFT(b,IDFT);
for(int i=0;i<=len;i++)
ans=(ans+(q[int(floor(b[i].x+0.5)+1)>>1]-1)%MOD)%MOD;
long long t=Manacher();
ans=(ans-t+MOD)%MOD;
printf("%lld",ans);
return 0;
}