• bzoj4503 两个串


    题目描述:

    给一个文本串和一个模式串,模式串中有通配符$'?'$,

    问匹配多少次,哪里可以匹配。

    题解:

    极为暴力,$FFT$单字符匹配$26$次,总计$26*3=78$次$FFT$。

    其实有更好的方法我放在下一篇博客里

    代码:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const double Pi = acos(-1.0);
    const int N = 300050;
    struct cp
    {
        double x,y;
        cp(){}
        cp(double x,double y):x(x),y(y){}
        cp operator + (const cp&a)const{return cp(x+a.x,y+a.y);}
        cp operator - (const cp&a)const{return cp(x-a.x,y-a.y);}
        cp operator * (const cp&a)const{return cp(x*a.x-y*a.y,x*a.y+y*a.x);}
    };
    int to[4*N],lim=1,l;
    void fft(cp *a,int len,int k)
    {
        for(int i=0;i<len;i++)
            if(i<to[i])swap(a[i],a[to[i]]);
        for(int i=1;i<len;i<<=1)
        {
            cp w0(cos(Pi/i),k*sin(Pi/i));
            for(int j=0;j<len;j+=(i<<1))
            {
                cp w(1,0);
                for(int o=0;o<i;o++,w=w*w0)
                {
                    cp w1=a[j+o],w2 = a[j+o+i]*w;
                    a[j+o] = w1+w2;
                    a[j+o+i] = w1-w2;
                }
            }
        }
        if(k==-1)for(int i=0;i<len;i++)a[i].x/=len;
    }
    char s1[N],s2[N];
    int n,m,ans[N];
    cp a[4*N],b[4*N],c[4*N];
    bool vis[28];
    void sol(int x)
    {
        for(int i=0;i<lim;i++)a[i]=b[i]=cp(0,0);
        for(int i=0;i<n;i++)if(s1[i]=='a'+x)a[i].x=1;
        for(int i=0;i<m;i++)if(s2[i]=='a'+x)b[m-i-1].x=1;
        fft(a,lim,1),fft(b,lim,1);
        for(int i=0;i<lim;i++)c[i]=a[i]*b[i];
        fft(c,lim,-1);
        for(int i=0;i<lim;i++)ans[i]+=(int)(c[i].x+0.5);
    }
    int main()
    {
    //    freopen("6.in","r",stdin);
        scanf("%s%s",s1,s2);
        n = strlen(s1),m = strlen(s2);
        for(int i=0;i<n;i++)vis[s1[i]-'a']=1;
        for(int i=0;i<m;i++)if(s2[i]!='?')vis[s2[i]-'a']=1;
        while(lim<2*(n+m))lim<<=1,l++;
        for(int i=1;i<lim;i++)to[i]=((to[i>>1]>>1)|((i&1)<<(l-1)));
        for(int i=0;i<26;i++)if(vis[i])sol(i);
        int cnt = 0,sum = 0;
        for(int i=0;i<m;i++)if(s2[i]!='?')cnt++;
        for(int i=m-1;i<n;i++)if(ans[i]==cnt)sum++;
        printf("%d
    ",sum);
        for(int i=m-1;i<n;i++)if(ans[i]==cnt)printf("%d
    ",i-m+1);
        return 0;
    }
  • 相关阅读:
    .NET Demon为Visual Studio提供持续编译和测试功能
    java面试题:字符串的排列算法
    JS实现IP地址判断
    明茨伯格管理进行时的读书感想:好书,适合有一定管理经验的人沉淀
    N个小时学MM IMG设定_存货管理和盘点 <四>
    上线第一天
    ISurfaceOp 接口生成等高线(一)
    出差合肥,路经武汉,后到长沙
    新博客
    出差合肥,路经武汉,后到长沙2
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10284263.html
Copyright © 2020-2023  润新知