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

链接:点击打开链接

题意:给出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;
}


 

你可能感兴趣的:(源码,动态规划,ACM)