• 【BZOJ4259】残缺的字符串(FFT)


    【BZOJ4259】残缺的字符串(FFT)

    题面

    给定两个字符串(|S|,|T|),两个字符串中都带有通配符。

    回答(T)(S)中出现的次数。

    (|T|,|S|<=300000)

    题解

    两个串基本一样。。

    现在(S)串中也存在通配符,所以在函数后面再额外乘上一个(S[i])就行了。

    拆开式子后是三个卷积的形式。

    时间复杂度(O(nlogn))

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 888888
    const double Pi=acos(-1);
    struct Complex{double a,b;}A1[MAX],B1[MAX],A2[MAX],B2[MAX],A3[MAX],B3[MAX],W[MAX],F[MAX];
    Complex operator+(Complex a,Complex b){return (Complex){a.a+b.a,a.b+b.b};}
    Complex operator-(Complex a,Complex b){return (Complex){a.a-b.a,a.b-b.b};}
    Complex operator*(Complex a,Complex b){return (Complex){a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a};}
    int n,m,r[MAX],N,Z;
    int pos[MAX],ans,l;
    char S[MAX],T[MAX];
    void FFT(Complex *P,int opt)
    {
    	for(int i=1;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
    	for(int i=1;i<N;i<<=1)
    		for(int p=i<<1,j=0;j<N;j+=p)
    			for(int k=0;k<i;++k)
    			{
    				Complex w=(Complex){W[N/i*k].a,W[N/i*k].b*opt};
    				Complex X=P[j+k],Y=w*P[j+k+i];
    				P[j+k]=X+Y;P[i+j+k]=X-Y;
    			}
    	if(opt==-1)for(int i=0;i<N;++i)P[i].a/=N;
    }
    int main()
    {
    	scanf("%d%d",&m,&n);
    	scanf("%s",T);scanf("%s",S);
    	for(N=1;N<=(n+m-2);N<<=1)++l;
    	for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    	for(int i=1;i<N;i<<=1)
    		for(int k=0;k<i;++k)W[N/i*k]=(Complex){cos(k*Pi/i),sin(k*Pi/i)};
    	for(int i=0;i<n;++i)
    	{
    		int x=((S[i]=='*')?0:(S[i]-96));
    		A1[i].a=x,A2[i].a=2*x*x,A3[i].a=x*x*x;
    	}
    	for(int i=0;i<m;++i)
    	{
    		int x=((T[m-i-1]=='*')?0:(T[m-i-1]-96));
    		B1[i].a=x,B2[i].a=x*x,B3[i].a=x*x*x;
    	}
    	FFT(A1,1);FFT(B1,1);FFT(A2,1);FFT(B2,1);FFT(A3,1);FFT(B3,1);
    	for(int i=0;i<N;++i)
    		F[i]=A1[i]*B3[i]-A2[i]*B2[i]+A3[i]*B1[i];
    	FFT(F,-1);
    	for(int i=m-1;i<n;++i)
    		if((int)(F[i].a+0.5)==0)pos[++ans]=i-m+1;
    	printf("%d
    ",ans);
    	for(int i=1;i<=ans;++i)printf("%d ",pos[i]+1);puts("");
    	return 0;
    }
    
    
  • 相关阅读:
    Python程序编译成二进制的方法及比较:nuitka与pyinstaller
    Cython的使用
    Go高性能之方法接收器 指针vs值
    Trzsz 文件传输利器
    让你的Mac iTerm优雅的上传下载文件
    彻底搞懂之C++智能指针
    万能Debug神器之GDB的使用手册
    一种快速判断点在多边形内的算法
    理解点线拓扑关系的计算原理
    bootstrap 不常用的属性
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8798460.html
Copyright © 2020-2023  润新知