# BZOJ 3160 万径人踪灭 FFT+Manacher

7 篇文章 0 订阅
225 篇文章 13 订阅

## 代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100010
#define M 262144
#define pi acos(-1)
#define mod 1000000007
using namespace std;
typedef long long ll;
int n,m,L;
char s[N];
char ss[N<<1];
struct complex
{
double r,i;
complex(double x=0.0,double y=0.0){r=x,i=y;}
complex operator + (const complex a)
{return complex(r+a.r,i+a.i);}
complex operator - (const complex a)
{return complex(r-a.r,i-a.i);}
complex operator * (const complex a)
{return complex(r*a.r-i*a.i,r*a.i+i*a.r);}
}a[M],b[M];
int rev[M];
void FFT(complex *a,int f)
{
for(int i=0;i<n;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
for(int h=2;h<=n;h<<=1)
{
complex wn(cos(2*pi*f/h),sin(2*pi*f/h));
for(int i=0;i<n;i+=h)
{
complex w(1,0);
for(int j=0;j<(h>>1);j++,w=w*wn)
{
complex t=w*a[i+j+(h>>1)];
a[i+j+(h>>1)]=a[i+j]-t;
a[i+j]=a[i+j]+t;
}
}
}
if(f==-1)for(int i=0;i<n;i++)a[i].r/=n;
}
int p[N<<1];
int powtwo[N<<1];
void pre()
{
n=strlen(s+1);
ss[0]='&',ss[1]='^';
for(int i=1;i<=n;i++)
{
ss[i<<1]=s[i];
ss[i<<1|1]='^';
}
n++,n<<=1;
}
void manacher()
{
int ret=0,mx=0,id=0;
for(int i=1;i<n;i++)
{
if(mx>i)p[i]=min(p[2*id-i],mx-i);
else p[i]=1;
while(ss[i-p[i]]==ss[i+p[i]])p[i]++;
if(mx<p[i]+i)mx=p[i]+i,id=i;
}
}
void init()
{
powtwo[0]=1;
for(int i=1;i<=2*n;i++)
powtwo[i]=(powtwo[i-1]<<1)%mod;
}
int ans;
int f[N<<1];
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
n--;
int nn=n;
init();
for(int i=0;i<=n;i++)
{
a[i].r=(s[i+1]=='a')?1:0;
b[i].r=a[i].r;
a[i].i=b[i].i=0;
}
m=2*n,L=0;
for(n=1;n<=m;n<<=1)L++;
for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
FFT(a,1),FFT(b,1);
for(int i=0;i<=n;i++)a[i]=a[i]*b[i];
FFT(a,-1);
for(int i=0;i<=m;i++)
{
int tmp=(int)(a[i].r+0.1);
f[i]=f[i]+tmp;
}
m=2*nn,L=0;
for(n=1;n<=m;n<<=1)L++;
for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0;i<=nn;i++)
{
a[i].r=(s[i+1]=='b')?1:0;
b[i].r=a[i].r;
a[i].i=b[i].i=0;
}
FFT(a,1),FFT(b,1);
for(int i=0;i<=n;i++)a[i]=a[i]*b[i];
FFT(a,-1);
for(int i=0;i<=m;i++)
{
int tmp=(int)(a[i].r+0.1);
f[i]=f[i]+tmp;
}
for(int i=0;i<=m;i++)
{
int tmp=(f[i]+1)/2;
if(tmp>=0)
ans=(((ans+powtwo[tmp])%mod-1)%mod+mod)%mod;
}
pre();
manacher();
for(int i=0;i<=n;i++)ans=((ans-p[i]/2)%mod+mod)%mod;
printf("%d\n",ans);
}
03-03 678
04-14 27

09-01 127
08-16 242
03-15 229
05-25 3428
04-24 694
03-19 257
02-26 279
12-27 5695
04-29 462
03-07 236
07-21 29
09-02 185
04-07 2861
03-08 31
07-02 516

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

wzq_QwQ

¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。