zoukankan      html  css  js  c++  java
  • 【Luogu】P2536病毒检测(Trie上DP)

      题目链接

      这道题我写了个01DP,f[i][j]表示跑到Trie上第i个节点,匹配到字符串第j位行不行

      然后重点在*号无限匹配怎么处理

      经过一番脑洞我们可以发现*号无限匹配可以拆成两种情况:

      1:匹配数无条件+1,但是字符串仍然匹配到底j位

      2:直接跳过去了qwq

      对应设计状态转移方程就好了

      然后这个算法……我卡时卡空间勉强过

      卡时不知道怎么办……也许能循环展开什么的?

      卡空间的话,可以设滚动数组。

      f[i][j]中的i不再代表Trie上第i个节点,而是代表深度第i层的节点

      DP的时候用dfs的方法DP,DP完了统计一下就可以把原来叶子占用的空间清掉腾给别人

      Orz rqy,这真是个神办法

      

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cctype>
    #include<queue>
    #define maxn 505
    #define maxl 1020
    using namespace std;
    int tree[maxn*maxn][10],tot;
    int fail[maxn*maxn];
    char s[maxl];
    char c[maxl];
    int pnt[maxn];
    bool f[200000][maxn];
    
    inline int count(char i){
        if(i=='A')    return 0;
        if(i=='T')    return 1;
        if(i=='C')    return 2;
        if(i=='G')    return 3;
        if(i=='*')    return 4;
        return 5;
    }
    
    void update(int x){
        int n=strlen(c+1),now=0;
        for(int i=1;i<=n;++i){
            if(tree[now][count(c[i])]==0)    tree[now][count(c[i])]=++tot;
            now=tree[now][count(c[i])];
        }
        pnt[x]=now;
        return;
    }
    
    void makefail(){
        queue<int>q;
        for(int i=0;i<6;++i)
            if(tree[0][i])    q.push(tree[0][i]);
        while(!q.empty()){
            int from=q.front();    q.pop();
            for(int i=0;i<6;++i){
                int &now=tree[from][i];
                if(now==0){
                    now=tree[fail[from]][i];
                    continue;
                }
                fail[now]=tree[fail[from]][i];
                q.push(now);
            }
        }
        return;
    }
    
    
    int main(){
        scanf("%s",s+1);int len=strlen(s+1);
        int n;    scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%s",c+1);
            update(i);
        }
        //makefail();
        f[0][0]=1;
        for(int i=0;i<=tot;++i){
            for(register int j=0;j<len;++j){
                if(s[j+1]=='A')    if(tree[i][0])    f[tree[i][0]][j+1]|=f[i][j];
                if(s[j+1]=='T')    if(tree[i][1])    f[tree[i][1]][j+1]|=f[i][j];
                if(s[j+1]=='C')    if(tree[i][2])    f[tree[i][2]][j+1]|=f[i][j];
                if(s[j+1]=='G')    if(tree[i][3])    f[tree[i][3]][j+1]|=f[i][j];
                if(s[j+1]=='?')
                    for(int k=0;k<5;++k)
                        if(tree[i][k])    f[tree[i][k]][j+1]|=f[i][j];
                if(s[j+1]=='*'){
                    f[i][j+1]|=f[i][j];
                    for(int k=0;k<5;++k)
                        if(tree[i][k])    f[tree[i][k]][j]|=f[i][j];
                }
            }
            for(int j=0;j<5;++j)    f[tree[i][j]][len]|=f[i][len];
        }
        int ans=n;
        for(int i=1;i<=n;++i)
            if(f[pnt[i]][len]==1)    ans--;
        printf("%d
    ",ans);
        return 0;
    }
    
    /*
    A*G?C
    3
    AGTC
    AGTGTC
    AGTGC 
    */
  • 相关阅读:
    iOS多线程的初步研究(十)-- dispatch同步
    iOS 几种定时器
    iOS 如何计算UIWebView的ContentSize
    iOS 如何计算UIWebView的ContentSize
    iOS: NSTimer使用小记
    iOS: NSTimer使用小记
    使用Objective-C的+(void)initialize初始化static变量
    使用Objective-C的+(void)initialize初始化static变量
    拒绝从入门到放弃_《Python 核心编程 (第二版)》必读目录
    拒绝从入门到放弃_《Python 核心编程 (第二版)》必读目录
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8711084.html
Copyright © 2011-2022 走看看