首页 > 代码库 > BZOJ4503: 两个串
BZOJ4503: 两个串
传送门
FFT竟然还能解决字符串问题..
但是这个数据好像太水了,KMP瞎搞搞就能过。
考虑一下,如果不考虑问号,那么一个点匹配肯定存在的是$\sum (s1_i-s2_j)^2=0$,那么考虑存在?的情况。很显然,改成这样的即可:
$\sum (s1_i-s2_j)^2 s2_j$
化开即为$\sum s1_i^2s2_j+s2_j^3-2 \times s1_is2_j^2$
可以把$s2$reverse,然后$[M-1,N-1]$即为答案。
//BZOJ4503//by Cydiater//2017.2.11#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <queue>#include <map>#include <cstdlib>#include <cmath>#include <ctime>#include <iomanip>#include <algorithm>#include <bitset>#include <set>#include <vector>#include <complex>using namespace std; #define ll long long#define up(i,j,n) for(int i=j;i<=n;i++)#define down(i,j,n) for(int i=j;i>=n;i--)#define cmax(a,b) a=max(a,b)#define cmin(a,b) a=min(a,b)#define db double#define Plur complex<double>const int MAXN=5e5+5;const int oo=0x3f3f3f3f;const db PI=acos(-1);char s1[MAXN],s2[MAXN];Plur A[MAXN],B[MAXN],A2[MAXN],B2[MAXN],P1[MAXN],P2[MAXN],P3[MAXN];int N,M,NM,ans=0;namespace FFT{ Plur omega[MAXN],Invomega[MAXN]; void Prepare(int LIM){ up(i,0,LIM-1){ omega[i]=Plur(cos(2*PI*i/LIM),sin(2*PI*i/LIM)); Invomega[i]=conj(omega[i]); } } void Transform(int N,Plur *A,Plur *w){ int pos=0; up(i,0,N-1){ if(pos<i)swap(A[i],A[pos]); for(int tmp=N>>1;(pos^=tmp)<tmp;tmp>>=1); } for(int l=2;l<=N;l<<=1){ int delta=l>>1; for(int j=0;j<N;j+=l)up(k,0,delta-1){ Plur tmp=A[j+k+delta]*w[N/l*k]; A[j+delta+k]=A[j+k]-tmp; A[j+k]+=tmp; } } } void DFT(int N,Plur *A){ Transform(N,A,omega); } void IDFT(int N,Plur *A){ Transform(N,A,Invomega); up(i,0,N-1)A[i]/=N; }}namespace solution{ void Prepare(){ scanf("%s",s1);scanf("%s",s2); N=strlen(s1);M=strlen(s2); reverse(s2,s2+M); NM=N+M-1; up(i,0,M-1)if(s2[i]==‘?‘)s2[i]=‘a‘-1; int ind=0; while((1<<ind)<NM)ind++; NM=(1<<ind); up(i,0,N-1)A[i].real(s1[i]-‘a‘+1); up(i,0,N-1)A2[i].real((s1[i]-‘a‘+1)*(s1[i]-‘a‘+1)); up(i,0,M-1)B[i].real(s2[i]-‘a‘+1); up(i,0,M-1)B2[i].real((s2[i]-‘a‘+1)*(s2[i]-‘a‘+1)); } int col(int pos){return (int)(P1[pos].real()+P2[pos].real()-P3[pos].real()-P3[pos].real()+0.5);} void Solve(){ FFT::Prepare(NM); FFT::DFT(NM,A);FFT::DFT(NM,A2); FFT::DFT(NM,B);FFT::DFT(NM,B2); up(i,0,NM-1)P1[i]=A2[i]*B[i]; up(i,0,NM-1)P3[i]=A[i]*B2[i]; FFT::IDFT(NM,P1); FFT::IDFT(NM,P3); int tmp=0; up(i,0,M-1)tmp+=(s2[i]-‘a‘+1)*(s2[i]-‘a‘+1)*(s2[i]-‘a‘+1); up(i,0,NM-1)P2[i].real(tmp); up(i,M-1,N-1)if(col(i)==0)ans++; cout<<ans<<endl; up(i,M-1,N-1)if(col(i)==0){ printf("%d\n",i-(M-1)); } }}int main(){ //freopen("input.in","r",stdin); using namespace solution; Prepare(); Solve(); return 0;}
BZOJ4503: 两个串
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。