zoukankan      html  css  js  c++  java
  • bzoj 4503 两个串

    Description

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

    Input

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

    Output

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

    Sample Input

    ababcadaca
    a?a

    Sample Output

    3
    0
    5

    HINT

    S 长度不超过 10^5, T 长度不会超过 S。 S 中只包含小写字母, T中只包含小写字母和“?”

    将b串反转

     设两个串的距离值为∑(ai-aj)2aiaj=∑ai3aj+∑aiaj3-∑2ai2aj2

    当为*时ai为0

    FFT直接上

    #include<bits/stdc++.h>
    #define pi acos(-1)
    #define maxn 300010
    using namespace std;
    struct Complex{
        double r,i;
        Complex(double x=0,double y=0){r=x,i=y;}
        Complex operator + (Complex x){return Complex(r+x.r,i+x.i);}
        Complex operator - (Complex x){return Complex(r-x.r,i-x.i);}
        Complex operator * (Complex x){return Complex(r*x.r-i*x.i,r*x.i+i*x.r);}
    }A[maxn],B[maxn],C[maxn];
    char a[maxn],b[maxn];
    int rev[maxn];
    int N,L;
    int k1[maxn],k2[maxn];
    int l1,l2;
    int ans;
    int k[maxn];
    void FFT(Complex a[],int n,int f){
        for(int i=0;i<n;++i)
            if(i<rev[i])
                swap(a[i],a[rev[i]]);
        for(int i=2;i<=n;i<<=1){
            Complex wn=Complex(cos(2*pi/i),sin(2*pi/i)*f);
            for(int j=0;j<n;j+=i){
                Complex w=Complex(1,0);
                for(int k=0;k<(i>>1);++k,w=w*wn){
                    Complex tmp1=a[j+k],tmp2=a[j+k+(i>>1)]*w;
                    a[j+k]=tmp1+tmp2;a[j+k+(i>>1)]=tmp1-tmp2;
                }
            }
        }
        if(f==-1)for(int i=0;i<n;++i)a[i].r/=n;
    }
    void init(){
        scanf("%s%s",a,b);
        l1=strlen(a);l2=strlen(b);
        for(int i=0;i<l1;++i)k1[i]=a[i]-'a'+1;
        for(int i=0;i<(l2>>1);++i)swap(b[i],b[l2-i-1]);
        for(int i=0;i<l2;++i)
            if(b[i]=='?')k2[i]=0;
            else k2[i]=b[i]-'a'+1;
        N=1,L=0;while(N<l1+l2)N<<=1,L++;
        for(int i=0;i<N;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
    }
    void work(){
        for(int i=0;i<N;++i)A[i]=Complex(k1[i],0);
        for(int i=0;i<N;++i)B[i]=Complex(k2[i]*k2[i]*k2[i],0);
        FFT(A,N,1);FFT(B,N,1);
        for(int i=0;i<N;++i)C[i]=C[i]+(A[i]*B[i]);
        for(int i=0;i<N;++i)A[i]=Complex(k1[i]*k1[i]*k1[i],0);
        for(int i=0;i<N;++i)B[i]=Complex(k2[i],0);
        FFT(A,N,1);FFT(B,N,1);
        for(int i=0;i<N;++i)C[i]=C[i]+(A[i]*B[i]);
        for(int i=0;i<N;++i)A[i]=Complex(k1[i]*k1[i]*2,0);
        for(int i=0;i<N;++i)B[i]=Complex(k2[i]*k2[i],0);
        FFT(A,N,1);FFT(B,N,1);
        for(int i=0;i<N;++i)C[i]=(C[i]-(A[i]*B[i]));
        FFT(C,N,-1);
        for(int i=l2-1;i<l1;++i)
            if(C[i].r<0.5)k[++ans]=i-l2+1;
        printf("%d
    ",ans);
        for(int i=1;i<=ans;++i)
            printf("%d
    ",k[i]);
    }
    int main(){
        init();
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    五大常用算法之四:回溯法
    五大常用算法之三:贪心算法
    五大常用算法之二:动态规划算法
    SSH 只能用于远程 Linux 主机?那说明你见识太小了!
    通过Heketi管理GlusterFS为K8S集群提供持久化存储
    php大文件(视频)分片上传
    php大文件(视频)上传讨论
    php大文件(视频)上传分享
    php大文件(视频)上传问题
    php大文件(视频)上传方法
  • 原文地址:https://www.cnblogs.com/117208-/p/5370018.html
Copyright © 2011-2022 走看看