hdu 4057 Rescue the Rabbit(AC自动机+状压dp)

题目链接:hdu 4057 Rescue the Rabbit

题意:

给出一些模式串,每个串有一定的价值,现在构造一个长度为M的串,问最大的价值为多少,每个模式串最多统计一次。

题解:

由于每个模式串最多统计一次,所以我们要考虑记录是否已经存在该串。

考虑dp[i][j][k]表示当前考虑到i的长度,存在的串的组合为j,在AC自动机上走到了k这个节点的状态。

然后转移一下就能将所有能到达的状态走到。然后取一个最大值就行了。

 1 #include<bits/stdc++.h>
 2 #define mst(a,b) memset(a,b,sizeof(a))
 3 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 4 using namespace std;
 5 
 6 const int AC_N=20000,tyn=4;
 7 struct AC_automation{
 8     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
 9     inline int getid(char x)
10     {
11         if(x=='A')return 0;
12         if(x=='T')return 1;
13         if(x=='G')return 2;
14         return 3;
15     }
16     void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));}
17     void init(){tot=-1,fail[0]=-1,nw();}
18     void insert(char *s,int idx,int x=0){
19         for(int len=strlen(s),i=0,w;i<len;x=tr[x][w],i++)
20             if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot;
21         cnt[x]|=1<<(idx-1);
22     }
23     void build(int head=1,int tail=0){
24         for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i];
25         while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++)
26             if(tr[x][i])
27             {
28                 fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i];
29                 cnt[tr[x][i]]|=cnt[fail[tr[x][i]]];
30             }
31             else tr[x][i]=tr[fail[x]][i];
32     }
33 }AC;
34 
35 int dp[2][1<<10][1001],n,m,val[20],now,U,ans;
36 char s[1000];
37 
38 int getans(int u)
39 {
40     int ans=0;
41     for(int i=1;u;u>>=1,i++)if(u&1)ans+=val[i];
42     return ans;
43 }
44 
45 int main(){
46     while(~scanf("%d%d",&n,&m))
47     {
48         now=0,ans=-INT_MAX;AC.init();
49         F(i,1,n)
50         {
51             scanf("%s%d",s,val+i);
52             AC.insert(s,i);
53         }
54         AC.build(),U=(1<<n)-1;
55         mst(dp[now],0),dp[now][0][0]=1;
56         F(i,1,m)
57         {
58             now^=1,mst(dp[now],0);
59             F(r,0,U)F(j,0,AC.tot)
60             if(dp[now^1][r][j])
61                 F(k,0,3)dp[now][r|AC.cnt[AC.tr[j][k]]][AC.tr[j][k]]=1;
62         }
63         F(j,0,U)F(i,0,AC.tot)if(dp[now][j][i]){ans=max(ans,getans(j));break;}
64         if(ans>=0)printf("%d\n",ans);
65         else puts("No Rabbit after 2012!");
66     }
67     return 0;
68 }
View Code

 

转载于:https://www.cnblogs.com/bin-gege/p/7252617.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值