• bzoj 4259 4259: 残缺的字符串【FFT】


    和bzoj 4503 https://www.cnblogs.com/lokiii/p/10032311.html 差不多,就是再乘上一个原串字符
    有点卡常,先在点值下算最后一起IDFT

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int N=1100005;
    int n,m,bt,lm,re[N],tot;
    long long x[N],y[N];
    double sm;
    char s[N],t[N];
    struct cd
    {
        double a,b;
        cd(double A=0,double B=0)
        {
            a=A,b=B;
        }
        cd operator + (const cd &x) const
        {
            return cd(a+x.a,b+x.b);
        }
        cd operator - (const cd &x) const
        {
            return cd(a-x.a,b-x.b);
        }
        cd operator * (const cd &x) const
        {
            return cd(a*x.a-b*x.b,a*x.b+b*x.a);
        }
    }a[N],b[N],c[N];
    void dft(cd a[],int f)
    {
        for(int i=0;i<lm;i++)
            if(i<re[i])
                swap(a[i],a[re[i]]);
        for(int i=1;i<lm;i<<=1)
        {
            cd wi=cd(cos(M_PI/i),f*sin(M_PI/i));
            for(int k=0;k<lm;k+=(i<<1))
            {
                cd w=cd(1,0),x,y;
                for(int j=0;j<i;j++)
                {
                    x=a[j+k],y=w*a[i+j+k];
                    a[j+k]=x+y,a[i+j+k]=x-y;
                    w=w*wi;
                }
            }
        }
        if(f==-1)
            for(int i=0;i<lm;i++)
                a[i].a/=lm;
    }
    int main()
    {
        scanf("%d%d%s%s",&n,&m,t,s);
    	for(int i=0,j=n-1;i<j;i++,j--)
    		swap(t[i],t[j]);
        for(int i=0;i<n;i++)
            x[i]=(t[i]=='*')?0:t[i]-'a'+1,a[i].a=x[i]*x[i]*x[i];
        for(int i=0;i<m;i++)
            y[i]=(s[i]=='*')?0:s[i]-'a'+1,b[i].a=y[i];
        for(bt=0;(1<<bt)<=n+m;bt++);
        lm=1<<bt;
        for(int i=0;i<lm;i++)
            re[i]=(re[i>>1]>>1)|((i&1)<<(bt-1));
    	dft(a,1),dft(b,1);
    	for(int i=0;i<lm;i++)
    		c[i]=c[i]+a[i]*b[i];
    	for(int i=0;i<lm;i++)
    		a[i]=cd(x[i],0),b[i]=cd(y[i]*y[i]*y[i],0);
    	dft(a,1),dft(b,1);
    	for(int i=0;i<lm;i++)
    		c[i]=c[i]+a[i]*b[i];
    	for(int i=0;i<lm;i++)
    		a[i]=cd(x[i]*x[i],0),b[i]=cd(y[i]*y[i],0);
    	dft(a,1),dft(b,1);
    	for(int i=0;i<lm;i++)
    		c[i]=c[i]-a[i]*b[i]*cd(2,0);
    	dft(c,-1);
    	for(int i=n-1;i<m;i++)
    		if((int)(c[i].a+0.5)==0)
    			tot++;
        printf("%d
    ",tot);
        for(int i=n-1;i<m;i++)
            if((int)(c[i].a+0.5)==0)
                printf("%d ",i-n+2);
        return 0;
    }
    
  • 相关阅读:
    有一天,我们能这样相爱吗?
    端午节来源六说
    一个ini类代替缓存使用
    创意生活可爱香皂
    漂亮的韩国发饰
    Oracle中PL/SQL单行函数和组函数详解
    真正爱你的女人是这样的
    执子之手,与子偕老。你同意么?
    男人如茶
    Oracle SQL 內置函數大全
  • 原文地址:https://www.cnblogs.com/lokiii/p/10036135.html
Copyright © 2020-2023  润新知