hdu4057 Rescue the Rabbit,AC自动机,状态压缩dp
题意:给n(<=10)个串,每个串有个权值,给一个长度(<=100),问这个长度能构造出的最大权值的串是多少。
一个串只能被计算一次权值。
将这些串建trie树,那么树节点不会超过1000个。
然后状态压缩dp,状态有2^10=1024种,节点数1000个,每次转移有四种,共有100次转移,转移用AC自动机优化就是O(1)。
因此复杂度就是O(1000*1024*100*4)。实际会更小一些,因为树节点没有那么多。每次可转移的也没有那么多。
dp[i][j][k]表示走i步,包含j中二进制位为1的串,当前状态是k是否可达。
i那一维可用滚动数组弄掉。
题意:给n(<=10)个串,每个串有个权值,给一个长度(<=100),问这个长度能构造出的最大权值的串是多少。
一个串只能被计算一次权值。
将这些串建trie树,那么树节点不会超过1000个。
然后状态压缩dp,状态有2^10=1024种,节点数1000个,每次转移有四种,共有100次转移,转移用AC自动机优化就是O(1)。
因此复杂度就是O(1000*1024*100*4)。实际会更小一些,因为树节点没有那么多。每次可转移的也没有那么多。
dp[i][j][k]表示走i步,包含j中二进制位为1的串,当前状态是k是否可达。
i那一维可用滚动数组弄掉。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define NN 1040
int tottrie,q[NN],root;
int ptr[500];
char s[NN];
struct trie{
int fail;
int son[4];
int flag;
void init(){
fail=0;
flag=0;
memset(son,0,sizeof(son));
}
}tt[NN];
void init(){
ptr['A']=0;ptr['T']=1;ptr['C']=2;ptr['G']=3;
tottrie=0;
root=++tottrie;
tt[1].init();
}
void insert(char *a,int v){
int j=root;
int i;
while(*a){
i=ptr[*a];
if (!tt[j].son[i]) {tt[j].son[i]=++tottrie;tt[tottrie].init();}
j=tt[j].son[i];
a++;
}
tt[j].flag=1<<v;
}
void build_ac(){
int i,j,u,v;
int rear=0,front=0;
q[++rear]=root;
while(front<rear){
u=q[++front];
for(i=0;i<4;++i){
j=tt[u].fail;
while(j&&!tt[j].son[i]) j=tt[j].fail;
if (tt[u].son[i]){
v=tt[u].son[i];
if (!j) tt[v].fail=root;
else{
tt[v].fail=tt[j].son[i];
tt[v].flag|=tt[tt[v].fail].flag;
}
q[++rear]=v;
}
else {
if (!j) tt[u].son[i]=root;
else tt[u].son[i]=tt[j].son[i];
}
}
}
}
int v[NN];
int dp[2][NN][NN];
const int inf =10000000;
int main(){
//freopen("gin.txt","r",stdin);
int i,j,l,o,pas,now,tn,n,k,ans,vv,tmp;
while(scanf("%d%d",&n,&k)!=EOF){
init();
for(i=1;i<=n;++i){
scanf("%s%d",s,&v[i]);
if (strlen(s)>k) continue;
insert(s,i-1);
}
build_ac();
memset(dp,0,sizeof(dp));
pas=0;now=1;
tn=1<<n;
dp[1][0][1]=1;
for(i=1;i<=k;++i){
pas=now;now=1-now;
for(j=1;j<=tottrie;++j)
for(l=0;l<tn;++l)
{dp[now][l][j]=0;}
for(j=1;j<=tottrie;++j){
for(l=0;l<tn;++l)if (dp[pas][l][j]){
for(o=0;o<4;++o){
vv=tt[j].son[o];
dp[now][l|tt[vv].flag][vv]=1;
}
}
}
}
ans=-inf;
for(i=1;i<=tottrie;++i){
for(j=0;j<tn;++j)if (dp[now][j][i]){
tmp=0;
for(l=0;l<n;++l){
if (j&(1<<l)) tmp+=v[l+1];
}
if (tmp>ans) ans=tmp;
}
}
if (ans<0) printf("No Rabbit after 2012!\n");
else printf("%d\n",ans);
}
return 0;
}