• Codeforces 86C Genetic engineering(AC自动机+DP)


    题目大概是给几个DNA片段,求构造一个长度n的字符串的方案数,要求这个字符串每个位置的字符都属于某个包含于此字符串的DNA片段。

    把那些DNA片段建一个AC自动机。考虑状态的表示:

    • dp[len][x][k]表示长度len且后缀状态为自动机结点x且后k位还不满足要求的方案数
    • 然后转移就是向自动机上四个方向的结点走,如果下一步结点x'是某DNA的后缀且长度比k大,那就是转移到dp[len+1][x'][0]否则转移到dp[len+1][x'][k+1]。另外因为DNA最长10,所以第三维k不会超过10。

    不过我还是看了别人代码才A掉这题。。忽略了某个结点不是一个DNA片段但其后缀可能是个DNA片段。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 using namespace std;
     5 int tn,ch[111][4],fail[111],flag[111];
     6 int idx[128];
     7 void insert(char *s,int k){
     8     int x=0;
     9     for(int i=0; s[i]; ++i){
    10         int y=idx[s[i]];
    11         if(ch[x][y]==0) ch[x][y]=++tn;
    12         x=ch[x][y];
    13     }
    14     flag[x]=k;
    15 }
    16 void getFail(){
    17     queue<int> que;
    18     for(int i=0; i<4; ++i){
    19         if(ch[0][i]) que.push(ch[0][i]);
    20     }
    21     while(!que.empty()){
    22         int x=que.front(); que.pop();
    23         for(int i=0; i<4; ++i){
    24             if(ch[x][i]){
    25                 que.push(ch[x][i]);
    26                 fail[ch[x][i]]=ch[fail[x]][i];
    27                 flag[ch[x][i]]=max(flag[ch[x][i]],flag[ch[fail[x]][i]]);
    28             } else ch[x][i]=ch[fail[x]][i];
    29         }
    30     }
    31 }
    32 struct Node{
    33     int len,x,k;
    34     Node(int _l=0,int _x=0,int _k=0):len(_l),x(_x),k(_k){}
    35 };
    36 int d[1111][111][11];
    37 bool vis[1111][111][11];
    38 int main(){
    39     idx['A']=0; idx['C']=1; idx['G']=2; idx['T']=3;
    40     char str[11];
    41     int n,m;
    42     scanf("%d%d",&n,&m);
    43     for(int i=0; i<m; ++i){
    44         scanf("%s",str);
    45         insert(str,strlen(str));
    46     }
    47     getFail();
    48     d[0][0][0]=1;
    49     vis[0][0][0]=1;
    50     queue<Node> que;
    51     que.push(Node(0,0,0));
    52     while(!que.empty()){
    53         Node nd=que.front(); que.pop();
    54         int len=nd.len,x=nd.x,k=nd.k;
    55         if(len==n) continue;
    56         for(int i=0; i<4; ++i){
    57             if(k+1<=flag[ch[x][i]]){
    58                 d[len+1][ch[x][i]][0]+=d[len][x][k];
    59                 d[len+1][ch[x][i]][0]%=1000000009;
    60                 if(!vis[len+1][ch[x][i]][0]){
    61                     vis[len+1][ch[x][i]][0]=1;
    62                     que.push(Node(len+1,ch[x][i],0));
    63                 }
    64             }else{
    65                 if(k>=9) continue;
    66                 d[len+1][ch[x][i]][k+1]+=d[len][x][k];
    67                 d[len+1][ch[x][i]][k+1]%=1000000009;
    68                 if(!vis[len+1][ch[x][i]][k+1]){
    69                     vis[len+1][ch[x][i]][k+1]=1;
    70                     que.push(Node(len+1,ch[x][i],k+1));
    71                 }
    72             }
    73         }
    74         //vis[len][x][k]=0; //DAG
    75     }
    76     int res=0;
    77     for(int i=0; i<=tn; ++i){
    78         res+=d[n][i][0];
    79         res%=1000000009;
    80     }
    81     printf("%d",res);
    82     return 0;
    83 }
  • 相关阅读:
    poj1088 经典dp
    poj2301
    poj1050(nyoj104 zoj1074)dp问题
    hdu1003
    poj1001(高精度)
    图的深度优先遍历DFS
    jquery中attr和prop的区别
    Apache 配置域名入口路径
    关于启动定时器和取消定时器的问题
    Web攻防之XSS,CSRF,SQL注入
  • 原文地址:https://www.cnblogs.com/WABoss/p/5255282.html
Copyright © 2020-2023  润新知