zoukankan      html  css  js  c++  java
  • Codeforces 528D Fuzzy Search(FFT)

    【题目链接】 http://codeforces.com/problemset/problem/528/D

    【题目大意】

      给出一个母串,和一个子串,子串允许模糊匹配,模糊匹配的意思就是
      在母串一个范围内如果出现该位置的字符,就当匹配成功,求子串在母串中出现次数。

    【题解】

      寻找子串是否在母串中出现,只要看逆子串和母串的卷积,
      如果一个位置的卷积答案是等于m的那么就匹配,即子串出现一次。
      根据题目条件,我们发现
      子串可以匹配母串范围内的字符也就是子串在母串的某个位置可以有多个匹配满足
      也就是求柔性字符串匹配。
      对于柔性字符串匹配来说,母串的同一个位置可以是多个字符,
      因此我们将其单独拆开来,对于每个字符求出一个匹配数组,
      将这个数组和子串做卷积运算,最后累积答案,最终答案为m的话,就是子串出现了一次
      最后计算答案数组中等于m的数量,就是匹配的次数
      这样就能够解决柔性匹配问题。

    【代码】

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <cstring> 
    using namespace std;
    typedef long long LL;
    const int N=524300;
    int pos[N],nxt[4],pre[4],mp[N][4],c[N],num[N],n,m,k;
    char s[N],t[N];
    int Tr(char c){
        if(c=='A')return 0;
        if(c=='C')return 1;
        if(c=='G')return 2;
        if(c=='T')return 3;
    }
    namespace FFT{
        struct comp{
            double r,i;
            comp(double _r=0,double _i=0):r(_r),i(_i){}
            comp operator +(const comp&x){return comp(r+x.r,i+x.i);}
            comp operator -(const comp&x){return comp(r-x.r,i-x.i);}
            comp operator *(const comp&x){return comp(r*x.r-i*x.i,i*x.r+r*x.i);}
            comp conj(){return comp(r,-i);}
        }A[N],B[N];
        const double pi=acos(-1.0);
        void FFT(comp a[],int n,int t){
            for(int i=1;i<n;i++)if(pos[i]>i)swap(a[i],a[pos[i]]);
            for(int d=0;(1<<d)<n;d++){
                int m=1<<d,m2=m<<1;
                double o=pi*2/m2*t;
                comp _w(cos(o),sin(o));
                for(int i=0;i<n;i+=m2){
                    comp w(1,0);
                    for(int j=0;j<m;j++){
                        comp& A=a[i+j+m],&B=a[i+j],t=w*A;
                        A=B-t;
                        B=B+t;
                        w=w*_w;
                    }
                }
            }if(t==-1)for(int i=0;i<n;i++)a[i].r/=n;
        }
        void mul(int n,int m,int k,int x){
            int i,j;
            for(i=0;i<k;i++)A[i]=comp(mp[i][x],i<m?Tr(t[m-i-1])==x:0);
            j=__builtin_ctz(k)-1;
            for(int i=0;i<k;i++){pos[i]=pos[i>>1]>>1|((i&1)<<j);} 
            FFT(A,k,1);
            for(int i=0;i<k;i++){
                j=(k-i)&(k-1);
                B[i]=(A[i]*A[i]-(A[j]*A[j]).conj())*comp(0,-0.25);
            }FFT(B,k,-1);
            for(int i=0;i<k;i++)c[i]+=(int)(B[i].r+0.5);
        }
    }
    int main(){
        scanf("%d%d%d%s%s",&n,&m,&k,s,t);
        int N=1,ans=0;; while(N<n+m-1)N<<=1;
        memset(pre,-1,sizeof(pre));
        memset(nxt,-1,sizeof(nxt));
        for(int i=0;i<n;i++){
            int x=Tr(s[i]);
            mp[i][x]=1;
            for(int j=0;j<4;j++)if(~pre[j]&&i-pre[j]<=k)mp[i][j]=1;
            pre[x]=i;
        }
        for(int i=n-1;i>=0;i--){
        	int x=Tr(s[i]);
            for(int j=0;j<4;j++)if(~nxt[j]&&nxt[j]-i<=k)mp[i][j]=1;
            nxt[x]=i;
        }for(int i=0;i<4;i++)FFT::mul(n,m,N,i);
        for(int i=m-1;i<n;i++)if(c[i]==m)ans++;
        printf("%d
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    【C++】资源管理
    【Shell脚本】逐行处理文本文件
    【算法题】rand5()产生rand7()
    【Shell脚本】字符串处理
    Apple iOS产品硬件参数. 不及格的程序员
    与iPhone的差距! 不及格的程序员
    iPhone游戏 Mr.Karoshi"过劳死"通关. 不及格的程序员
    XCode V4 发布了, 苹果的却是个变态. 不及格的程序员
    何时readonly 字段不是 readonly 的?结果出呼你想象!!! 不及格的程序员
    object file format unrecognized, invalid, or unsuitable Command 不及格的程序员
  • 原文地址:https://www.cnblogs.com/forever97/p/codeforces528d.html
Copyright © 2011-2022 走看看