zoukankan      html  css  js  c++  java
  • 【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;
    }
    
    
  • 相关阅读:
    Java实现各种内部排序算法
    Java实现堆排序(大根堆)
    Java对象的序列化和反序列化
    Java实现链式存储的二叉查找树(递归方法)
    337. House Robber III(包含I和II)
    318. Maximum Product of Word Lengths
    114. Flatten Binary Tree to Linked List
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    96. Unique Binary Search Trees(I 和 II)
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8798460.html
Copyright © 2011-2022 走看看