题面传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3160
思路:首先题目中不要连续的回文串,那么答案就是总的回文串-连续回文串
连续回文串用manacher就可以O(n)搞出来
现在的问题是求总的回文串。
既然是回文串,我们就想到枚举对称轴
为了方便表示在字符的夹缝的对称轴,下标*2,下标为奇数则为夹缝。
令f[i]为对称轴为i时两边相同的字符对数,那么答案就是sigma (2^f[i])-1
现在的问题是快速求f[i]
令a[i]表示原串第i个为是否为a,b[i]表示原串第i个为是否为b;
那么f[i]=sigma a[j]*a[k]+sigma b[x]+b[y] (j+k=i,x+y=i,j<=k,x<=y)
这不就是卷积吗
上FFT搞一搞就可以了
被递归版代码常数吓傻,卡着时限A...
#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int maxn=270010,mod=1000000007;
const double pi=M_PI;
using namespace std;
struct plex{
double r,i;
}tmp[maxn];
plex operator +(plex a,plex b){return (plex){a.r+b.r,a.i+b.i};}
plex operator -(plex a,plex b){return (plex){a.r-b.r,a.i-b.i};}
plex operator *(plex a,plex b){return (plex){a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r};}
struct DFT{
plex a[maxn];
void fft(int bg,int step,int size,int op){
if (size==1) return;
fft(bg,step<<1,size>>1,op),fft(bg+step,step<<1,size>>1,op);
plex w=(plex){1,0},t=(plex){cos(2*pi/size),sin(2*pi*op/size)};
int p=bg,p0=bg,p1=bg+step;
for (int i=0;i<size/2;i++){
tmp[p]=a[p0]+w*a[p1];
tmp[p+size/2*step]=a[p0]-w*a[p1];
p+=step,p0+=step*2,p1+=step*2,w=w*t;
}
for (int i=bg;size;size--,i+=step) a[i]=tmp[i];
}
}a,b;
int f[maxn<<1],len,n,nn,POW[maxn],ans;char str[maxn],s[maxn<<1];
int manacher(){
int i,res=0;
for (s[0]='$',s[1]='#',i=1;i<=n;i++) s[i<<1]=str[i-1],s[(i<<1)|1]='#';
n=(n<<1)|1;
int mx=1,id=1;
for (int i=1;i<=n;i++){
f[i]=min(f[id+id-i],mx-i);
for (;s[i+f[i]]==s[i-f[i]];) f[i]++;
if (f[i]+i>mx) mx=f[i]+i,id=i;
res+=f[i]>>1,res%=mod;
}
return res;
}
int main(){
POW[0]=1;for (int i=1;i<maxn;i++) POW[i]=(POW[i-1]<<1)%mod;
scanf("%s",str),n=strlen(str);
for (nn=1;nn<(n<<1);nn<<=1);
for (int i=0;i<n;i++) a.a[i].r=(str[i]=='a'?1.0:0.0);
for (int i=0;i<n;i++) b.a[i].r=(str[i]=='b'?1.0:0.0);
a.fft(0,1,nn,1),b.fft(0,1,nn,1);
for (int i=0;i<nn;i++)
a.a[i]=a.a[i]*a.a[i]+b.a[i]*b.a[i];
a.fft(0,1,nn,-1);
for (int i=0;i<nn;i++) a.a[i].r/=nn;
for (int i=0;i<nn;i++){
int x=(int)(round(a.a[i].r)+1)>>1;
ans=(ans+POW[x]-1)%mod;
}
//int t=(int)clock();
printf("%d\n",(ans-manacher()+mod)%mod);//
//printf("%d\n",(int)clock()-t);
return 0;
}