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 }

 

posted @ 2016-03-08 19:26  WABoss  阅读(519)  评论(0编辑  收藏  举报