[BZOJ4503]两个串
Posted jefflyy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ4503]两个串相关的知识,希望对你有一定的参考价值。
$\newcommand{align}[1]{\begin{align*}#1\end{align*}}$如果$S_{i\cdots i+m-1}$与$T$相等,那么$\align{\sum\limits_{j=0}^{m-1}\left(S_{i+j}-T_j\right)^2T_j}=0$(令通配符为$T_i=0$),展开得到$\align{\sum\limits_{j=0}^{m-1}S^2_{i+j}T_j-2\sum\limits_{j=0}^{m-1}S_{i+j}T^2_j+\sum\limits_{j=0}^{m-1}T_j^3}$,这种错位相乘直接翻转卷积即可
这大概是一个套路...学习之
#include<stdio.h> #include<math.h> #include<string.h> typedef double du; const du eps=1e-5; struct complex{ du x,y; complex(du a=0,du b=0){x=a;y=b;} }; complex operator+(complex a,complex b){return complex(a.x+b.x,a.y+b.y);} complex operator-(complex a,complex b){return complex(a.x-b.x,a.y-b.y);} complex operator*(complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);} template<class T>void swap(T&a,T&b){ T c=a; a=b; b=c; } int rev[262144],N; void pre(int n){ int i,k; for(N=1,k=0;N<n;N<<=1)k++; for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1)); } void fft(complex*a,int on){ int i,j,k; complex t; for(i=0;i<N;i++){ if(i<rev[i])swap(a[i],a[rev[i]]); } for(i=2;i<=N;i<<=1){ for(j=0;j<N;j+=i){ for(k=0;k<i>>1;k++){ t=complex(cos(k*M_PI/(i/2)),on*sin(k*M_PI/(i/2)))*a[i/2+j+k]; a[i/2+j+k]=a[j+k]-t; a[j+k]=a[j+k]+t; } } } if(on==-1){ for(i=0;i<N;i++)a[i].x/=N; } } char s[100010],t[100010]; complex a[262144],b[262144],c[262144],d[262144]; int main(){ int n,m,i,x,ans; double t3; scanf("%s%s",s,t); n=strlen(s); m=strlen(t); for(i=0;i>1;i++)swap(s[n-1-i],s[i]); for(i=0;i<n;i++){ x=s[i]-‘a‘+1; a[i].x=x*x; c[i].x=x; } t3=0; for(i=0;i<m;i++){ if(t[i]==‘?‘) x=0; else x=t[i]-‘a‘+1; b[i].x=x; d[i].x=x*x; t3+=x*x*x; } pre(n<<1); fft(a,1); fft(b,1); for(i=0;i<N;i++)a[i]=a[i]*b[i]; fft(a,-1); fft(c,1); fft(d,1); for(i=0;i<N;i++)b[i]=c[i]*d[i]; fft(b,-1); ans=0; for(i=0;i<=n-m;i++){ if(fabs((a[n-1-i]-b[n-1-i]*2+t3).x)<=eps)ans++; } printf("%d\n",ans); for(i=0;i<=n-m;i++){ if(fabs((a[n-1-i]-b[n-1-i]*2+t3).x)<=eps)printf("%d\n",i); } }
以上是关于[BZOJ4503]两个串的主要内容,如果未能解决你的问题,请参考以下文章