• Fuzzy Search


    题意:

    考虑模板串B和给定串A,给定K,对于模板串上给定位置j的字符,如果能在给定串上i左右K个字符内找到相同字符,则说可以匹配。

    问有多少匹配。

    解法:

    考虑对于每一种字符分开求。

    对于当前字符ch,将B串中为此字符的位置标为1其他位置为0,将A串中所有可以匹配ch的位置标为1,其他为0,这样

    记$c_i$表示以 i 为起点字符ch可以匹配到几个。

    $$c_i = sum_{ 0 leq j<m} { b_j a_{i+j} }$$

    $$c_i = sum_{0 leq k leq i+m} {revb_k a_{m+i-k}}$$

    卷积即可。

    #include <bits/stdc++.h>
    
    #define PI acos(-1)
    
    const int N = 200010;
    
    using namespace std;
    
    struct EX
    {
        double real,i;
        EX operator+(const EX tmp)const{return (EX){real+tmp.real, i+tmp.i};};
        EX operator-(const EX tmp)const{return (EX){real-tmp.real, i-tmp.i};};
        EX operator*(const EX tmp)const{return (EX){real*tmp.real - i*tmp.i, real*tmp.i + i*tmp.real};};
    };
    
    int R[N<<2];
    
    void DFT(EX a[],int n,int tp_k)
    {
        for(int i=0;i<n;i++) if(i<R[i]) swap(a[i],a[R[i]]);
        for(int d=1;d<n;d<<=1)
        {
            EX wn = (EX){cos(PI/d), sin(PI/d)*tp_k};
            for(int i=0;i<n;i += (d<<1))
            {
                EX wt = (EX){1,0};
                for(int k=0;k<d;k++, wt = wt*wn)
                {
                    EX A0 = a[i+k], A1 = wt * a[i+k+d];
                    a[i+k] = A0+A1;
                    a[i+k+d] = A0-A1;
                }
            }
        }
        if(tp_k==-1)
            for(int i=0;i<n;i++) a[i] = (EX){a[i].real/n, a[i].i/n};
    }
    
    int n,m,K;
    EX A[N<<2],B[N<<2],C[N<<2];
    char S[N],S2[N];
    bool del[N];
    
    void calc(char ch,int tot)
    {
        memset(B,0,sizeof(B));
        memset(A,0,sizeof(A));
        int cnt_S2 = 0;
        for(int i=0;i<m;i++) if(S2[i]==ch) B[m-i] = (EX){1,0}, cnt_S2++;
        int tp = -1;
        for(int i=0;i<n;i++)
        {
            if(S[i]==ch) tp = i;
            if(tp!=-1 && i-tp<=K) A[i] = (EX){1,0};
        }
        tp = -1;
        for(int i=n-1;i>=0;i--)
        {
            if(S[i]==ch) tp = i;
            if(tp!=-1 && tp-i<=K) A[i] = (EX){1,0};
        }
        DFT(A,tot,1);
        DFT(B,tot,1);
        for(int i=0;i<tot;i++) C[i] = A[i]*B[i];
        DFT(C,tot,-1);
        for(int i=0;i<n;i++)
        {
            int tmp = C[i+m].real+0.5;
            if(tmp<cnt_S2) del[i] = 1;
        }
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&K);
        scanf("%s%s",S,S2);
        int L = 0,tot;
        while((1<<L)<n+m) L++;
        tot = (1<<L);
        for(int i=1;i<tot;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
        calc('A',tot);
        calc('T',tot);
        calc('C',tot);
        calc('G',tot);
        int ans = 0;
        for(int i=0;i<=n-m;i++) if(!del[i]) ans++;
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    ok6410 u-boot-2012.04.01移植六完善MLC NAND支持
    Apache XAMPP Fails to start under Windows XP
    Gridview导出到Excel
    PKU 1511 Invitation Cards (SPFA+邻接表)
    等待队列(二)
    HDU--杭电--1253--胜利大逃亡--广搜
    Java菜鸟学习笔记--Exception篇(一):异常简介
    jquery的DOM操作
    Windows下Postgre SQL数据库通过Slony-I 实现数据库双机同步备份
    POJ 2418 ,ZOJ 1899 Hardwood Species
  • 原文地址:https://www.cnblogs.com/lawyer/p/7163094.html
Copyright © 2020-2023  润新知