zoukankan      html  css  js  c++  java
  • BZOJ4259 残缺的字符串(FFT)

      两个串匹配时相匹配的位置位置差是相同的,那么翻转一个串就变成位置和相同,卷积的形式。

      考虑如何使用卷积体现两个位置能否匹配。一个暴力的思路是每次只考虑一种字符,将其在一个串中设为1,并在另一个串中将不是该字符且不是通配符的设为1,卷积结果不为0则无法匹配。这样要跑26次1e6的FFT,就算有6s也……事实上这在luogu就可以过了。

      当然这是因为luogu的评测机太神了,我们考虑一些更靠谱的方法。考虑用一些奇技淫巧。

      定义两个字符串的距离函数为dis(a,b)=Σ(a[i]-b[i])2a[i]b[i]。通配符在字符串中视为0。可以发现这个式子非常妙的将通配和直接匹配都包括进去了,不同位置间不会相互影响,如果dis=0则相同≠0则不同。将这个式子展开,做三次FFT再加起来就可以了。

      居然最慢的只跑了半秒……

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 1050000
    int n,m,r[N],t;
    char s1[N],s2[N];
    bool f[N];
    double s[N];
    const double PI=3.14159265358979324;
    const double eps=1E-2;
    struct complex
    {
        double x,y;
        complex operator +(const complex&a) const
        {
            return (complex){x+a.x,y+a.y};
        }
        complex operator -(const complex&a) const
        {
            return (complex){x-a.x,y-a.y};
        }
        complex operator *(const complex&a) const
        {
            return (complex){x*a.x-y*a.y,x*a.y+y*a.x};
        }
    }a[N],b[N];
    void DFT(int n,complex *a,int p)
    {
        for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
        for (int i=2;i<=n;i<<=1)
        {
            complex wn=(complex){cos(2*PI/i),p*sin(2*PI/i)};
            for (int j=0;j<n;j+=i)
            {
                complex w=(complex){1,0};
                for (int k=j;k<j+(i>>1);k++,w=w*wn)
                {
                    complex x=a[k],y=w*a[k+(i>>1)];
                    a[k]=x+y,a[k+(i>>1)]=x-y;
                }
            }
        }
    }
    void mul(int n,complex *a,complex *b)
    {
        for (int i=0;i<n;i++) a[i].y=a[i].x-b[i].x,a[i].x=a[i].x+b[i].x;
        DFT(n,a,1);
        for (int i=0;i<n;i++) a[i]=a[i]*a[i];
        DFT(n,a,-1);
        for (int i=0;i<n;i++) a[i].x=a[i].x/n/4;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4259.in","r",stdin);
        freopen("bzoj4259.out","w",stdout);
        const char LL[]="%I64d";
    #else
        const char LL[]="%lld";
    #endif
        m=read(),n=read();
        scanf("%s%s",s1,s2);
        reverse(s1,s1+m);
        t=1;while (t<=n+m) t<<=1;
        for (int i=0;i<t;i++) r[i]=(r[i>>1]>>1)|(i&1)*(t>>1);
        for (int i=1;i<=n-m+1;i++) f[i]=1;
        for (int i=0;i<t;i++) a[i].x=a[i].y=b[i].x=b[i].y=0;
        for (int i=0;i<m;i++) a[i].x=(s1[i]=='*'?0:s1[i]-96);
        for (int i=0;i<m;i++) a[i].x=a[i].x*a[i].x*a[i].x;
        for (int i=0;i<n;i++) b[i].x=(s2[i]=='*'?0:s2[i]-96);
        mul(t,a,b);
        for (int i=0;i<t;i++) s[i]+=a[i].x;
        for (int i=0;i<t;i++) a[i].x=a[i].y=b[i].x=b[i].y=0;
        for (int i=0;i<m;i++) a[i].x=(s1[i]=='*'?0:s1[i]-96);
        for (int i=0;i<m;i++) a[i].x=a[i].x*a[i].x;
        for (int i=0;i<n;i++) b[i].x=(s2[i]=='*'?0:s2[i]-96);
        for (int i=0;i<n;i++) b[i].x=b[i].x*b[i].x;
        mul(t,a,b);
        for (int i=0;i<t;i++) s[i]-=2*a[i].x;
        for (int i=0;i<t;i++) a[i].x=a[i].y=b[i].x=b[i].y=0;
        for (int i=0;i<m;i++) a[i].x=(s1[i]=='*'?0:s1[i]-96);
        for (int i=0;i<n;i++) b[i].x=(s2[i]=='*'?0:s2[i]-96);
        for (int i=0;i<n;i++) b[i].x=b[i].x*b[i].x*b[i].x;
        mul(t,a,b);
        for (int i=0;i<t;i++) s[i]+=a[i].x;
        for (int i=m-1;i<n;i++) if (s[i]>eps) f[i-m+2]=0;
        int cnt=0;
        for (int i=1;i<=n;i++) cnt+=f[i];
        cout<<cnt<<endl;
        for (int i=1;i<=n;i++) if (f[i]) printf("%d ",i);
        return 0;
    }
  • 相关阅读:
    Linux中的文件夹的增删改查命令和文件的增删改查命令
    xshell开源软件
    2020090808redis之linux的gcc的升级安装(八)
    2020090807redis之windows安装(七)
    2020090806redis之理解(六)
    2020090805redis之nosql的四大分类(五)
    每个牛逼的人都有一段苦逼的岁月,但是只要像SB一样坚持,终将牛逼
    2020090804redis之数据库的搭建(四)
    2020090803redis之大数据3V+3高(三)
    2020090802redis之非关系 数据库nosql(二)
  • 原文地址:https://www.cnblogs.com/Gloid/p/9452441.html
Copyright © 2011-2022 走看看