0
点赞
收藏
分享

微信扫一扫

HDOJ 4057 - Rescue the Rabbit 简单的AC自动机+状态压缩DP


                 题意:

                         众所周知..DNA序列由"A","G","T","C"组成....

                         现在N个DNA序列(每个长度没说..假设都小于1000吧...1<=N<=10)...并且告诉每个DNA序列能得到的分数Wi,(|Wi|<=100)...

                         若一个DNA串包含其中的某些串..那么得分就是包括的串分数之和(一个串不管出现了多少次..只算一次)..

                         问..若构造长度为M(1<=M<=100)的DNA序列...能得到的最大分数为多少...

                 题解:

                          裸AC自动机...然后10个DNA子串...状态压缩DP...复杂度有些高 100*1000*1024*4...好久没写AC自动机了..差点写跪....再一个写程序的时候memset最好直接用for循环去代替吧..常数比较大....


Program:

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<algorithm>
#include<string.h>
#define MAXN 10002
using namespace std;
struct node
{
int son[4],fail,w;
}P[MAXN];
char s[1005];
bool dp[2][1015][1<<10];
int val[1<<10],turn[30],num;
void initial(int h)
{
int x;
for (x=0;x<4;x++) P[h].son[x]=0;
P[h].fail=P[h].w=0;
}
void Built_Trie(int n)
{
int h,k,t,x,i,y,len;
initial(0),num=0;
for (t=0;t<n;t++)
{
scanf("%s%d",s+1,&val[t]),len=strlen(s+1);
if (len>100) { val[t]=0; continue; }
h=0;
for (i=1;i<=len;i++)
{
x=turn[s[i]-'A'];
if (!P[h].son[x]) P[h].son[x]=++num,initial(num);
h=P[h].son[x];
}
P[h].w|=1<<t;
}
}
void Built_AC()
{
int h,k,x;
queue<int> Q;
while (Q.size()) Q.pop();
for (x=0;x<4;x++)
if (P[0].son[x])
Q.push(P[0].son[x]);
while (Q.size())
{
h=Q.front(),Q.pop();
for (x=0;x<4;x++)
{
k=P[h].fail;
while (k && !P[k].son[x]) k=P[k].fail;
P[P[h].son[x]].fail=P[k].son[x];
if (!P[h].son[x])
P[h].son[x]=P[k].son[x];
else
{
Q.push(P[h].son[x]);
k=P[h].fail;
while (1)
{
P[P[h].son[x]].w|=P[P[k].son[x]].w,k=P[k].fail;
if (!k) break;
}
}
}
}
}
int AC_DP(int n,int L)
{
int l,w,h,x,h1,w1,temp,ans=-1,g=0;
memset(dp,false,sizeof(dp));
dp[g][0][0]=true;
for (l=1;l<=L;l++)
{
g=1-g;
for (h=0;h<=num;h++)
for (w=0;w<(1<<n);w++)
dp[g][h][w]=false;
for (h=0;h<=num;h++)
for (w=0;w<(1<<n);w++)
if (dp[1-g][h][w])
for (x=0;x<4;x++)
{
h1=P[h].son[x];
w1=w|P[h1].w;
dp[g][h1][w1]=true;
}
}
for (h=0;h<=num;h++)
for (w=0;w<(1<<n);w++)
if (dp[g][h][w])
dp[g][0][w]=true;
for (w=0;w<(1<<n);w++)
if (dp[g][0][w])
{
temp=0;
for (x=0;x<n;x++)
if (w & 1<<x)
temp+=val[x];
ans=max(ans,temp);
}
return ans;
}
int main()
{
int n,l,ans;
turn['A'-'A']=0,turn['G'-'A']=1,
turn['T'-'A']=2,turn['C'-'A']=3;
while (~scanf("%d%d",&n,&l))
{
Built_Trie(n);
Built_AC();
ans=AC_DP(n,l);
if (ans<0) puts("No Rabbit after 2012!");
else printf("%d\n",ans);
}
return 0;
}



举报

相关推荐

0 条评论