# [BZOJ3160] 万径人踪灭

### 试题分析

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>

using namespace std;
#define LL long long
#define Pi 3.1415926535
const LL Mod = 1e9+7;

inline LL read(){
LL x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const LL MAXN = 4e5+5;
const LL INF = 2147483600;

char str2[MAXN+1],str[MAXN+1]; LL N;
LL Len[MAXN+1],f[MAXN+1];

LL lim=1,l,r[MAXN+1];
struct cpx{
double a,b;
cpx (double aa=0,double bb=0){a=aa,b=bb;}
}a[MAXN+1],b[MAXN+1];
cpx operator + (cpx a,cpx b){return cpx(a.a+b.a,a.b+b.b);}
cpx operator - (cpx a,cpx b){return cpx(a.a-b.a,a.b-b.b);}
cpx operator * (cpx a,cpx b){return cpx(a.a*b.a - a.b*b.b , a.a*b.b + a.b*b.a);}
LL M; LL rev[MAXN+1];

inline void FFT(cpx *A,LL type){
for(LL i=0;i<lim;i++) if(rev[i]>i) swap(A[rev[i]],A[i]);
for(LL mid=1;mid<lim;mid<<=1){
cpx Wn( 1.0*cos(Pi/mid) , 1.0*type*sin(Pi/mid) );
for(LL R=(mid<<1),j=0;j<lim;j+=R){
cpx w(1,0);
for(LL k=0;k<mid;k++,w=w*Wn){
cpx x = A[j+k] , y = w*A[j+k+mid];
A[j+k] = x + y; A[j+k+mid] = x - y;
}
}
} return ;
}
inline void work(char ch){
for(LL i=0;i<lim;i++) a[i]=cpx(str[i]==ch,0),cout<<a[i].a<<" "; cout<<endl;
FFT(a,1); for(LL i=0;i<lim;i++) a[i]=a[i]*a[i]; FFT(a,-1);
for(LL i=1;i<=2*N;i++) f[i]+=((LL)(a[i].a*1.0/lim+0.5)+1)/2,cout<<((LL)(a[i].a*1.0/lim+0.5)+1)/2<<" ";
for(LL i=1;i<=2*N;i++) cout<<a[i].a<<" "; cout<<endl;
cout<<endl;
}
LL Pw[MAXN+1];

int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
scanf("%s",str2+1); N=strlen(str2+1);
LL Mx=-INF,pos=0; Pw[0]=1;
for(LL i=1;i<=N;i++) str[i]=str2[i];
for(LL i=1;i<=N;i++) Pw[i]=Pw[i-1]*2LL%Mod;
while(lim<=2*N) lim<<=1,++l;

LL ans=0; puts(str+1);
for(LL i=0;i<lim;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
work('a'); work('b');
for(LL i=1;i<=2*N;i++) ans=(ans+Pw[f[i]]-1)%Mod,cout<<f[i]<<" ";
cout<<endl;

str[0]='%'; str[2*N+1]='#';
for(LL i=1;i<=N;i++) str[2*i]=str2[i],str[2*i-1]='#';
for(LL i=1;i<=2*N;i++){
if(Mx>i) Len[i]=min(Mx-i,Len[2*pos-i]); else Len[i]=1;
while(Len[i]<i&&str[i+Len[i]]==str[i-Len[i]]) ++Len[i];
if(i+Len[i]>Mx) pos=i,Mx=i+Len[i];
}
for(LL i=1;i<=2*N;i++) ans=(ans-Len[i]/2+Mod)%Mod;
printf("%lld\n",ans);
return 0;
}

posted @ 2018-09-01 15:01  wxjor  阅读(114)  评论(0编辑  收藏  举报