您的位置:首页 > 其它

hdu4057(AC自动机+状态压缩dp)

2016-03-19 22:53 316 查看
链接:点击打开链接

题意:给出n段基因的价值和组成,求一个长度为l的价值大于零最大的基因价值

代码:

#include <queue>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int q[1005],dp[2][1005][(1<<10)+5];
int fail[100005],vis[100005],val[100005];
int str[100005][30],dis[100005];
int root,id;
int change(char c){
if(c=='A')return 0;
if(c=='T')return 1;
if(c=='G')return 2;
if(c=='C')return 3;
return 0;
}                                               //只有四个字母
void insert(char *s){
int u=0;
for(;*s;s++){
if(!str[u][change(*s)])
str[u][change(*s)]=root++;
u=str[u][change(*s)];
}
dis[u]|=(1<<(id-1));
id++;
}
void getfail(){
int u,v,i,l,r,temp;
l=0,r=0;
q[r++]=0;
while(l<r){
u=q[l++];
for(i=0;i<4;i++){
if(!str[u][i])
str[u][i]=str[fail[u]][i];
else
{
temp=str[u][i];
if(u)
fail[temp]=str[fail[u]][i];
dis[temp]|=dis[fail[temp]];
q[r++]=temp;
}
}
}
}                                               //自动机模板
int cal(int t,int m){
int i,ans;
ans=0;
for(i=0;i<m;i++)
if(t&(1<<i))
ans+=val[i];
return ans;
}                                               //计算出每个状态的价值
int main(){
int n,m,k,i,j,x,y,z,ans;
char s[1005];
while(scanf("%d%d",&m,&k)!=EOF){
root=id=1;
memset(str,0,sizeof(str));
memset(val,0,sizeof(val));
memset(dis,0,sizeof(dis));
memset(fail,0,sizeof(fail));
for(i=0;i<m;i++){
scanf("%s%d",s,&val[i]);
insert(s);
}
getfail();
memset(dp,0,sizeof(dp));
dp[0][0][0]=1;
for(x=0;x<k;x++){                           //空间不够,因此用滚动数组
memset(dp[(x+1)&1],0,sizeof(dp[(x+1)&1]));
for(y=0;y<root;y++)
for(z=0;z<(1<<m);z++)
if(dp[x&1][y][z])
for(j=0;j<4;j++){
dp[(x+1)&1][str[y][j]][z|dis[str[y][j]]]=dp[x&1][y][z];
}
}                                           //自动机+状态压缩dp的题还是很相似的
ans=-INF;
for(i=0;i<(1<<m);i++)
for(j=0;j<root;j++)
if(dp[k&1][j][i])
ans=max(ans,cal(i,m));
if(ans<0)
puts("No Rabbit after 2012!");
else
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: