zoukankan      html  css  js  c++  java
  • [AHOI2005]病毒检测

    题目描述

    科学家们在Samuel星球上的探险仍在继续。非常幸运的,在Samuel星球的南极附近,探险机器人发现了一个巨大的冰湖!机器人在这个冰湖中搜集到了许多RNA片段运回了实验基地。

    科学家们经过几个昼夜的研究,发现这些RNA片段中有许多是未知的病毒!

    每个RNA片段都是由A、C、T、G组成的序列。科学家们也总结出了Samuel星球上的“病毒模版片段”。一个模版片段是由A、C、T、G的序列加上通配符 和 ? 来表示。其中 的意思是可以匹配上0个或任意多个字符,而 ? 的意思是匹配上任意一个字母。

    如果一个RNA片段能够和“病毒模版片段”相匹配,那么这个RNA片段就是未知的病毒。

    例如,假设“病毒模版片段”为A*G?C。RNA片段:AGTC,AGTGTC都是未知的病毒,而RNA片段AGTGC则不是病毒。

    由于,机器人搜集的这些RNA片段中除去病毒的其他部分都具有非常高的研究价值。所以科学家们希望能够分辨出其中哪些RNA片段不是病毒,并将不是病毒的RNA片段运回宇宙空间站继续进行研究。

    科学家将这项任务交给了小联。现在请你为小联编写程序统计哪些RNA片段不是病毒。

    输入输出格式

    输入格式:
    第一行有一个字符串,由A、C、T、G、*、? 组成。表示“病毒模版片段”。“病毒模版片段”的长度不超过1000。第二行有一个整数N(0<N<500),表示机器人搜集到的RNA片段的数目。随后的N行,每一行有一个字符串,由A、C、T、G组成,表示一个RNA片段。每个RNA片段的长度不超过500。注意:“病毒模版片段”和RNA片段的长度都至少为1。

    输出格式:

    只有一行输出,为整数M,即不是病毒的RNA片段的数目。

    输入输出样例

    输入样例#1:

    A*G?C
        3
    AGTC
    AGTGTC
    AGTGC
    

    输出样例#1: 复制

    1
    

    说明

    输入中的RNA片段AGTGC不是病毒。


    有好多方法啊.....dp,字典树啊

    trie树

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    const int maxn=1000+233;
    using namespace std;
    char ch[maxn];
    typedef pair<int,int> par;
    int n;
    int ans;
    short moon[maxn];
    int tr[maxn*maxn][10];
    int no[maxn];
    int cnt,fin[maxn*maxn];
    inline short change(char c){
        if(c=='A')return 1;
        else if(c=='G')return 2;
        else if(c=='C')return 3;
        else if(c=='T')return 4;
        else if(c=='?')return 5;
        else return 6;
    }
    inline void add(){
        cin>>ch;
        int now=0;
        int len=strlen(ch);
        for(int i=0;i<len;i++)no[i]=change(ch[i]);
        for(int i=0;i<len;i++){
            if( tr[now][ no[i] ] )now=tr[now][ no[i] ];
            else cnt++,tr[now][no[i]]=cnt,now=cnt;
        }
        fin[now]++;
    }
    queue< pair<int,int> >q;
    inline void getans(int P){
        q.push(make_pair(1,0));
        while(!q.empty()){
            par p=q.front();q.pop();
            int now=p.second;//second匹配到位置<fir原字符 
            int point=p.first;
            if(moon[point]==6){
            q.push(make_pair(point+1,now));
            for(int i=1;i<5;i++){
            if(tr[now][i]){
                q.push(make_pair(point,tr[now][i]));
                q.push(make_pair(point+1,tr[now][i]));
            	}
          	  }
        	}
            else if(moon[point]==5)
            for(int i=1;i<5;i++){
            if(tr[now][i])q.push(make_pair(point+1,tr[now][i]));
            }
            else if(moon[point]){
            if(tr[now][moon[point]])
            q.push(make_pair(point+1,tr[now][moon[point]]));
            }
            if(point==P+1)
            ans+=fin[now],fin[now]=0;
        }
        cout<<n-ans;
    }
    int main(){
        cin>>ch+1;
        int len=strlen(ch+1);
        for(int i=1;i<=len;i++)moon[i]=change(ch[i]);
        cin>>n;
        for(int i=1;i<=n;i++)add();
        getans(len);
        return 0;
    }
    

    DP

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    const int maxn=1000+233;
    using namespace std;
    char ch[maxn];
    int c[maxn];
    int dp[maxn][maxn];
    char a[maxn];
    int n;
    int L;
    int ans;
    inline bool match(char x,char y){
        return (x==y)||(x=='?');
    }
    inline void add(){
        cin>>a+1;
        memset(c,0x3f,sizeof c);
        memset(dp,0,sizeof dp);
        int len=strlen(a+1);
        dp[0][0]=1;
        for(int i=1;i<=L;i++){
            if(ch[i]!='*')
                for(int j=1;j<=len;j++){
                    if(match(ch[i],a[j]))
                        if(dp[i-1][j-1]||ch[i-1]=='*'&&c[i-1]<j)
                    dp[i][j]=1;
                }
            else{
                if(i==1)dp[1][0]=1;
                for(int j=1;j<=len;j++){
                    dp[i][j]=dp[i-1][j]|dp[i][j-1];
                    if(dp[i][j])c[i]=min(c[i],j);
                }
            }
        }
        if(!dp[L][len])ans++;
    }
    int main(){
        cin>>ch+1;
        L=strlen(ch+1);
        cin>>n;
        for(;n;n--)add();
        cout<<ans;
        return 0;
    }
    
  • 相关阅读:
    30天自制操作系统之-第四天-
    30天自制操作系统之-第三天-
    30天自制操作系统之-第二天-
    30天自制操作系统之-第一天-
    c语言之连接符
    c语言之函数指针应用
    dpdk之路-环境部署
    linux系统裁剪
    redux和mobx比较(二)
    redux和mobx比较(一)
  • 原文地址:https://www.cnblogs.com/ck666/p/8232108.html
Copyright © 2011-2022 走看看