• bzoj4403 两个串


    Description

    兔子们在玩两个串的游戏。给定两个字符串S和T,兔子们想知道T在S中出现了几次,
    分别在哪些位置出现。注意T中可能有“?”字符,这个字符可以匹配任何字符。

    Input

    两行两个字符串,分别代表S和T

    Output

    第一行一个正整数k,表示T在S中出现了几次
    接下来k行正整数,分别代表T每次在S中出现的开始位置。按照从小到大的顺序输出,S下标从0开始。

    两个串a,b相等(b中有通配符)当且仅当Σ(a[i]-b[i])2b[i]=0,其中a[i],b[i]为对应字符的对应编号,且通配符对应0

    翻转S串并把T串用0补至与S等长后上式可化为卷积形式用fft计算

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    int N,P;
    const double pi=3.14159265358979323846;
    int r[524288];
    struct cplx{
        double a,b;
        inline cplx(double r=0,double i=0){a=r;b=i;}
        inline cplx operator+(cplx x){return cplx(a+x.a,b+x.b);}
        inline cplx operator-(cplx x){return cplx(a-x.a,b-x.b);}
        inline cplx operator*(cplx x){return cplx(a*x.a-b*x.b,a*x.b+b*x.a);}
    }a[524288],b[524288];
    void dft(cplx*a,int t){
        for(int i=0;i<N;i++)if(i>r[i])std::swap(a[i],a[r[i]]);
        for(int i=1;i<N;i<<=1){
            cplx w(cos(pi/i),t*sin(pi/i));
            for(int j=0;j<N;j+=i<<1){
                cplx e(1),*b=a+j,*c=b+i;
                for(int k=0;k<i;k++,e=e*w){
                    cplx x=b[k],y=c[k]*e;
                    b[k]=x+y,c[k]=x-y;
                }
            }
        }
    }
    char s1[200005],s2[200005];
    int v1[200005],v2[200005];
    int h1[200005],h2[200005];
    int as[200005],ap=0;
    int l1,l2,h3=0;
    int main(){
        input:{
            scanf("%s%s",s1,s2);
            l1=strlen(s1)-1;
            l2=strlen(s2)-1;
            for(int i=0;i<=l1;i++)v1[i]=s1[l1-i]-'a'+1;
            for(int i=0;i<=l2;i++)v2[i]=s2[i]!='?'?s2[i]-'a'+1:0;
            for(int i=0;i<=l2;i++)h3+=v2[i]*v2[i]*v2[i];
        }
        init:{
            for(N=2,P=0;N<=l1+1;N<<=1,++P);
            N<<=1,++P;
            for(int i=1;i<N;i++)r[i]=r[i>>1]>>1|(i&1)<<P;
        }
        calc:{
            for(int i=0;i<=l1;i++)a[i]=cplx(v1[i]*v1[i]);
            for(int i=0;i<=l1;i++)b[i]=cplx(v2[i]);
            for(int i=l1+1;i<N;i++)a[i]=b[i]=cplx();
            dft(a,1),dft(b,1);
            for(int i=0;i<N;i++)a[i]=a[i]*b[i];
            dft(a,-1);
            for(int i=0;i<=l1;i++)h1[i]=(int)(a[i].a/N+0.5);
            
            for(int i=0;i<=l1;i++)a[i]=cplx(v1[i]);
            for(int i=0;i<=l1;i++)b[i]=cplx(v2[i]*v2[i]);
            for(int i=l1+1;i<N;i++)a[i]=b[i]=cplx(0,0);
            dft(a,1),dft(b,1);
            for(int i=0;i<N;i++)a[i]=a[i]*b[i];
            dft(a,-1);
            for(int i=0;i<=l1;i++)h2[i]=(int)(a[i].a/N+0.5);
        }
        output:{
            for(int i=l1;i>=l2;i--)if(h1[i]-2*h2[i]+h3==0)as[ap++]=l1-i;
            printf("%d
    ",ap);
            for(int i=0;i<ap;i++)printf("%d
    ",as[i]);
        }
        return 0;
    }
  • 相关阅读:
    [jQuery学习系列六]6-jQuery实际操作小案例
    [Java拾遗一] XML的书写规范与解析.
    [数据库操作]Java中的JDBC的使用方法.
    [Java拾遗二]Tomact及Http 部分总结.
    [Java拾遗三]JavaWeb基础之Servlet
    [Java拾遗四]JavaWeb基础之Servlet_Request&&Response
    [Java拾遗五]使用Session防止表单重复提交
    [数据库连接池] Java数据库连接池--DBCP浅析.
    [开发工具]Java开发常用的在线工具
    [数据库连接池二]Java数据库连接池--C3P0和JDNI.
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5469179.html
Copyright © 2020-2023  润新知