题意:给定一个串,问有多少个满足位置对称的不连续回文子序列
考虑计算出出所有位置对称的回文子序列和所有连续回文子串
后者可以直接用
M
a
n
a
c
h
e
r
Manacher
Manacher求出
考虑前一部分怎么求
对于每个对称轴的位置
i
i
i单独考虑
发现和
a
,
b
a,b
a,b没有关系,只需要看
s
[
i
−
k
]
s[i-k]
s[i−k]和
s
[
i
+
k
]
s[i+k]
s[i+k]相等的个数就可以了
即
∑
k
[
s
[
i
+
k
]
=
=
s
[
i
−
k
]
]
\sum_{k}[s[i+k]==s[i-k]]
∑k[s[i+k]==s[i−k]]
考虑对于
a
,
b
a,b
a,b分别求出相等的个数再求和
比如
a
a
a,令所有为
a
a
a的位置为
1
1
1,否则为
0
0
0
那是
∑
k
s
[
i
−
k
]
∗
s
[
i
+
k
]
\sum_{k}s[i-k]*s[i+k]
∑ks[i−k]∗s[i+k]
f
f
t
fft
fft一下就可以了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=100005;
const int mod=1e9+7;
const double pi=acos(-1);
struct plx{
double x,y;
plx(double _x=0,double _y=0):x(_x),y(_y){}
friend inline plx operator +(const plx &a,const plx &b){
return plx(a.x+b.x,a.y+b.y);
}
friend inline plx operator -(const plx &a,const plx &b){
return plx(a.x-b.x,a.y-b.y);
}
friend inline plx operator *(const plx &a,const plx &b){
return plx(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
}a[N<<2],b[N<<2];
int rev[N<<2],lim=1,tim;
inline void fft(plx *f,int kd){
for(re int i=0;i<lim;i++)if(i<rev[i])swap(f[i],f[rev[i]]);
for(re int mid=1;mid<lim;mid<<=1){
plx now=plx(cos(pi/mid),kd*sin(pi/mid));
for(re int i=0;i<lim;i+=(mid<<1)){
plx w=plx(1,0);
for(re int j=0;j<mid;j++,w=w*now){
plx a0=f[i+j],a1=w*f[i+j+mid];
f[i+j]=a0+a1,f[i+j+mid]=a0-a1;
}
}
}
if(kd==-1)for(re int i=0;i<lim;i++)f[i].x/=lim;
}
char now[N<<2],s[N];
int n;
ll pw[N],ans;
int mx,mid,p[N<<2];
inline void add(ll &a,int b){
a=(a+b>=mod)?a+b-mod:a+b;
}
inline ll manacher(){
int len=strlen(s);ll res=0;
now[0]='!',now[1]='$',n=1;
for(re int i=0;i<len;i++){
now[++n]=s[i],now[++n]='$';
}
now[n+1]='@';
mx=mid=1;
for(re int i=1;i<=n;i++){
if(i<mx)p[i]=min(mx-i,p[2*mid-i]);
else p[i]=1;
while(now[i-p[i]]==now[i+p[i]])p[i]++;
if(mx<i+p[i])mx=i+p[i],mid=i;
add(res,(p[i])/2);
}return res;
}
int main(){
scanf("%s",s);
int len=strlen(s);
for(re int i=0;i<len;i++){
if(s[i]=='a')a[i].x=1;
else b[i].x=1;
}
while(lim<=len*2)lim<<=1,tim++;
for(re int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(tim-1));
fft(a,1);
fft(b,1);for(re int i=0;i<lim;i++) a[i]=a[i]*a[i],a[i]=a[i]+b[i]*b[i];
fft(a,-1);
pw[0]=1;for(re int i=1;i<=len;i++)pw[i]=pw[i-1]*2%mod;
for(re int i=0;i<=2*len+2;i++){
int k=(a[i].x+0.5);
k=(k+1)/2;add(ans,pw[k]-1);
}
cout<<(ans-manacher()+mod)%mod<<'\n';
}