POJ1699 Best Sequence(AC自动机+状压DP)

题目,求包含所有的给定的n个DNA片段的序列的最短长度。

AC自动机上的DP题。

  • dp[S][u]表示已经包含的DNA片段集合为S,且当前后缀状态是自动机第u个结点的最短长度
  • dp[0][0]=0
  • 我为人人+队列轻松转移。。
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 #define INF (1<<30)
 7 int tn,ch[222][4],fail[222],flag[222];
 8 int idx[128];
 9 void insert(char *s,int k){
10     int x=0;
11     for(int i=0; s[i]; ++i){
12         int y=idx[s[i]];
13         if(ch[x][y]==0) ch[x][y]=++tn;
14         x=ch[x][y];
15     }
16     flag[x]|=(1<<k);
17 }
18 void getfail(){
19     memset(fail,0,sizeof(fail));
20     queue<int> que;
21     for(int i=0; i<4; ++i){
22         if(ch[0][i]) que.push(ch[0][i]);
23     }
24     while(!que.empty()){
25         int x=que.front(); que.pop();
26         for(int i=0; i<4; ++i){
27             if(ch[x][i]){
28                 que.push(ch[x][i]);
29                 fail[ch[x][i]]=ch[fail[x]][i];
30                 flag[ch[x][i]]|=flag[ch[fail[x]][i]];
31             }else ch[x][i]=ch[fail[x]][i];
32         }
33     }
34 }
35 struct Node{
36     int s,x;
37     Node(int _s,int _x):s(_s),x(_x){}
38 };
39 int d[1<<10][222],vis[1<<10][222];
40 int main(){
41     idx['A']=0; idx['C']=1; idx['G']=2; idx['T']=3;
42     int t,n;
43     char str[22];
44     scanf("%d",&t);
45     while(t--){
46         tn=0;
47         memset(ch,0,sizeof(ch));
48         memset(flag,0,sizeof(flag));
49         scanf("%d",&n);
50         for(int i=0; i<n; ++i){
51             scanf("%s",str);
52             insert(str,i);
53         }
54         getfail();
55         for(int i=0; i<(1<<n); ++i){
56             for(int j=0; j<=tn; ++j) d[i][j]=INF;
57         }
58         d[0][0]=0;
59         memset(vis,0,sizeof(vis));
60         vis[0][0]=1;
61         queue<Node> que;
62         que.push(Node(0,0));
63         while(!que.empty()){
64             int s=que.front().s,x=que.front().x; que.pop();
65             for(int i=0; i<4; ++i){
66                 int ns=s|flag[ch[x][i]],nx=ch[x][i];
67                 if(d[ns][nx]>d[s][x]+1){
68                     d[ns][nx]=d[s][x]+1;
69                     if(!vis[ns][nx]){
70                         vis[ns][nx]=1;
71                         que.push(Node(ns,nx));
72                     }
73                 }
74             }
75             vis[s][x]=0;
76         }
77         int res=INF;
78         for(int i=0; i<=tn; ++i){
79             res=min(res,d[(1<<n)-1][i]);
80         }
81         printf("%d\n",res);
82     }
83     return 0;
84 } 

 

转载于:https://www.cnblogs.com/WABoss/p/5285573.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值