• 【[AHOI2005]病毒检测】


    (Trie) 树+搜索

    我用的是(dfs)

    首先对于将所有的RNA片段都建到(Trie)树里去,之后来匹配那个模板串就好了

    如果是匹配的位置是字母,那么我们就继续往下匹配

    如果是(?),我们必须要略过(Trie)树上的一位去匹配

    如果是(*),我们可以先考虑直接忽略这一位,也可以直接把这一位当成(?)来看,或者是在(Trie)树上略过一位,但是在模板串上的匹配仍为当前位置,这样就能实现在(Trie)树上忽略多位进行匹配了

    一旦某一位匹配成功了,我们如果还有状态到达这一步就没有什么必要了,所以开一个(bitset)来进行记忆化就好了

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<bitset>
    #define re register
    #define maxn 500005
    int son[maxn][4],flag[maxn];
    int n,m,cnt,L,ans;
    char S[1001],T[1001];
    std::bitset<1001> f[maxn];
    inline int read()
    {
        char c=getchar();
        int x=0;
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9')
          x=(x<<3)+(x<<1)+c-48,c=getchar();
        return x;
    }
    inline int ch(char p)
    {
        if(p=='A') return 0;
        if(p=='G') return 1;
        if(p=='T') return 2;
        if(p=='C') return 3;
    }
    inline void ins()
    {
        int len=strlen(S+1);
        int now=0;
        for(re int i=1;i<=len;i++)
        {
            if(!son[now][ch(S[i])]) son[now][ch(S[i])]=++cnt;
            now=son[now][ch(S[i])];
        }
        flag[now]++;
    }
    void dfs(int now,int t)
    {
        if(t==L+1)//匹配成功
        {
            ans+=flag[now];
            flag[now]=0;
            return;
        }
        if(f[now][t]) return;
        f[now][t]=1;//记忆化
        if(T[t]>='A'&&T[t]<='Z') 
        {
            if(!son[now][ch(T[t])]) return;
            dfs(son[now][ch(T[t])],t+1);
        }//是字母,那么我们就继续往下匹配
        else 
        {
            if(T[t]=='?') 
            {
                for(re int i=0;i<4;i++)
                if(son[now][i]) dfs(son[now][i],t+1);//在Trie上忽略一位,同时模板串匹配位置加1
            }
            if(T[t]=='*')
            {
                dfs(now,t+1);//忽略*,即用0个字符来代替它
                for(re int i=0;i<4;i++)
                if(son[now][i]) dfs(son[now][i],t+1),dfs(son[now][i],t);
                //第一个dfs直接把这一位当成$?$来看,第二个dfs就能实现一个*代替多个字符
            }
        }
    }
    int main()
    {
        scanf("%s",T+1);
        L=strlen(T+1);
        n=read();
        for(re int i=1;i<=n;i++)
            scanf("%s",S+1),ins();
        dfs(0,1);
        printf("%d
    ",n-ans);
        return 0;
    }
    
  • 相关阅读:
    python的logging模块
    python的random模块
    python3中time模块的用法及说明
    浅谈python模块的导入操作
    python3中,os.path模块下常用的用法总结
    OS模块的常用内置方法
    认识python中的set集合及其用法
    初识Python装饰器
    CentOS的软件包的管理之rpm和yum
    python中的函数对象与闭包函数
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207781.html
Copyright © 2020-2023  润新知