zoukankan      html  css  js  c++  java
  • BZOJ 4503 两个串 ——FFT

    【题目分析】

        定义两个字符之间的距离为

        (ai-bi)^2*ai*bi

        如果能够匹配,从i到i+m的位置的和一定为0

        但这和暴力没有什么区别。

        发现把b字符串反过来就可以卷积用FFT了。

        听说KMP+暴力可以卡到100ms以内(雾)

    【代码】

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define maxn 400005
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    
    const double pi=acos(-1.0);
    const double eps=1e-6;
    
    struct Complex{
        double x,y;
        Complex operator + (Complex a) const{Complex b; return b.x=x+a.x,b.y=y+a.y,b;}
        Complex operator - (Complex a) const{Complex b; return b.x=x-a.x,b.y=y-a.y,b;}
        Complex operator * (Complex a) const{Complex b; return b.x=x*a.x-y*a.y,b.y=x*a.y+y*a.x,b;}
    }a[maxn],b[maxn],c[maxn]; 
    
    char s[maxn],t[maxn];
    int A[maxn],B[maxn];
    int ls,lt,rev[maxn],n,m=1,len,ans[maxn];
    
    void FFT(Complex * x, int n, int f)
    {
    	F(i,0,n-1) if (rev[i]>i) swap(x[rev[i]],x[i]);
    	for (int m=2;m<=n;m<<=1)
    	{
    		int mid=m>>1;Complex wn; wn.x=cos(2.0*pi/m*f); wn.y=sin(2.0*pi/m*f);
    		for (int i=0;i<n;i+=m)
    		{
    			Complex w; w.x=1.0; w.y=0;
    			F(j,0,mid-1)
    			{
    				Complex a=x[i+j],b=x[i+j+mid]*w;
    				x[i+j]=a+b; x[i+j+mid]=a-b;
    				w=w*wn;
    			}
    		}
    	}
    }
    
    int main()
    {
    //	freopen("in.txt","r",stdin);
    	scanf("%s",s); scanf("%s",t);
    	ls=strlen(s); lt=strlen(t);
    	n=ls+lt+1;
    	while (m<=n) m<<=1,len++; n=m;
    	F(i,0,n-1)
    	{
    		int t=i,ret=0;
    		F(j,1,len) ret<<=1,ret|=t&1,t>>=1;
    		rev[i]=ret;
    	}
    	F(i,0,ls-1) A[i]=s[i]-'a'+1;
    	F(i,0,lt-1) {B[lt-i-1]=t[i]-'a'+1;if (t[i]=='?') B[lt-i-1]=0;}
    	
    	memset(a,0,sizeof a);
    	memset(b,0,sizeof b);
    	F(i,0,n-1) a[i].x=1;
    	F(i,0,n-1) b[i].x=B[i]*B[i]*B[i];
    	FFT(a,n,1); FFT(b,n,1);
    	F(i,0,n-1)
    		c[i]=a[i]*b[i];
    	
    	memset(a,0,sizeof a);
    	memset(b,0,sizeof b);
    	F(i,0,n-1) a[i].x=2*A[i];
    	F(i,0,n-1) b[i].x=B[i]*B[i];
    	FFT(a,n,1); FFT(b,n,1);
    	F(i,0,n-1)
    		c[i]=c[i]-a[i]*b[i];
    	
    	memset(a,0,sizeof a);
    	memset(b,0,sizeof b);
    	F(i,0,n-1) a[i].x=A[i]*A[i];
    	F(i,0,n-1) b[i].x=B[i];
    	FFT(a,n,1); FFT(b,n,1);
    	F(i,0,n-1) c[i]=c[i]+a[i]*b[i];
    	
    	FFT(c,n,-1);
    	F(i,0,n-1) c[i].x=c[i].x/n;
    	int cnt=0;
    	F(i,0,ls-lt) if (c[i+lt-1].x<0.5) cnt++;
    	printf("%d
    ",cnt);
    	F(i,0,ls-lt) if (c[i+lt-1].x<0.5) printf("%d
    ",i);
    }
    

      

  • 相关阅读:
    第08组 Alpha冲刺(4/6)
    2019 SDN阅读作业
    第08组 Alpha冲刺(3/6)
    2019 SDN上机第3次作业
    第08组 Alpha冲刺(2/6)
    答疑
    八、对抗样本1
    九、产生和防御对抗样本的新方法 | 分享总结--廖方舟(论文11)
    02-NLP-08-条件随机场与应用
    02-NLP-07-词向量及相关应用
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6395884.html
Copyright © 2011-2022 走看看