您的位置:首页 > 其它

hdu 4057(ac自动机+状态压缩dp)

2013-08-05 11:59 429 查看
题意:容易理解...

分析:题目中给的模式串的个数最多为10个,于是想到用状态压缩dp来做,它的状态范围为1-2^9,所以最大为2^10-1,那我们可以用:dp[i][j][k]表示长度为i,在trie树上的状态为j,压缩后的状态为k时的情况,知道怎么压缩之后这道题就是一道简单的ac自动机+压缩dp题了。

代码实现:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
struct node{
int next[4];
int fail;
int flag;
void init()
{
memset(next,0,sizeof(next));
fail=0;
flag=0;
}
}a[1005];

int n,len,tot;
int weight[15];
char keyword[105];
int dp[2][1005][1<<10];

void chushihua()
{
tot=0;
a[0].init();
memset(dp,0,sizeof(dp));
}

int hash(char x)
{
if(x=='A')
return 0;
else if(x=='C')
return 1;
else if(x=='G')
return 2;
else
return 3;
}

void insert(char *str,int biaohao)
{
int p=0,index;
for(;*str!='\0';str++)
{
index=hash(*str);
if(a[p].next[index]==0)
{
a[++tot].init();
a[p].next[index]=tot;
}
p=a[p].next[index];
}
a[p].flag=a[p].flag|(1<<biaohao);//状态标记
}

void build_fail()//建立trie图
{
queue<int>Q;
int p,son,cur,i;
Q.push(0);
while(!Q.empty())
{
p=Q.front();
Q.pop();
for(i=0;i<4;i++)
{
if(a[p].next[i]!=0)
{
son=a[p].next[i];
cur=a[p].fail;
if(p==0)
a[son].fail=0;
else
{
while(cur&&a[cur].next[i]==0)
cur=a[cur].fail;
a[son].fail=a[cur].next[i];
}
a[son].flag=a[son].flag|a[a[son].fail].flag;
Q.push(son);
}
else
a[p].next[i]=a[a[p].fail].next[i];
}
}
}

int get_weight(int x)
{
int i,sum=0;
for(i=0;i<n;i++)
if(x&(1<<i))
sum+=weight[i];
return sum;
}

void solve()
{
int i,j,k,l,son,res,temp;
dp[0][0][0]=1;
for(i=1;i<=len;i++)
{
memset(dp[i&1],0,sizeof(dp[i&1]));
for(j=0;j<=tot;j++)
{
for(l=0;l<(1<<n);l++)
{
if(dp[(i+1)&1][j][l]!=1)
continue;
for(k=0;k<4;k++)
{
son=a[j].next[k];
dp[i&1][son][l|a[son].flag]=1;
}
}
}
}
res=-100000000;
for(j=0;j<(1<<10);j++)
for(i=0;i<=tot;i++)
if(dp[len&1][i][j]==1)
{
temp=get_weight(j);
if(res<temp)
res=temp;
}
if(res<0)
printf("No Rabbit after 2012!\n");
else
printf("%d\n",res);
}

int main()
{
int i;
while(scanf("%d%d",&n,&len)!=EOF)
{
chushihua();
getchar();
for(i=0;i<n;i++)
{
scanf("%s%d",keyword,&weight[i]);
insert(keyword,i);
getchar();
}
build_fail();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: