http://acm.hdu.edu.cn/showproblem.php?pid=4057
Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1482 Accepted Submission(s): 430
2 4 ATG 4 TGC -3 1 6 TGC 4 4 1 A -1 T -2 G -3 C -4
4 4 No Rabbit after 2012!Hintcase 1:we can find a rabbit whose gene string is ATGG(4), or ATGA(4) etc. case 2:we can find a rabbit whose gene string is TGCTGC(4), or TGCCCC(4) etc. case 3:any gene string whose length is 1 has a negative W.
题意:
有ATCG4个字母,要求构成一个长度为l的字符串,给出n个模式串及其权值,问能构成的字符串中最大的权值和是多少,每个模式串只计算一次。
分析:
很容易想到是AC自动机。我们在AC自动机上找到长度为l的可行方案,并求出最大值即可。用dp[i][j][k]表示字符串长度为i时,AC自动机上第j个结点是否可达状态k。因为模式串只有10种,所以最多有2^10个状态,状压一下就行了,然后就是长度为i的字符串只由第i-1个变过来,所以可以用滚动数组。
/*
*
* Author : fcbruce <fcbruce8964@gmail.com>
*
* Time : Thu 13 Nov 2014 08:23:41 PM CST
*
*/
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#ifdef _WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define maxm
#define maxn 1007
using namespace std;
char gene[17][233];
int w[17];
int dp[2][maxn][2333];
int q[maxn<<1];
const int maxsize = 4;
struct ACauto
{
int ch[maxn][maxsize];
int val[maxn],last[maxn],nex[maxn];
int sz;
ACauto()
{
sz=1;
val[0]=0;
memset(ch[0],0,sizeof ch[0]);
}
void clear()
{
sz=1;
val[0]=0;
memset(ch[0],0,sizeof ch[0]);
}
int idx(char c)
{
switch (c)
{
case 'A': return 0;
case 'T': return 1;
case 'C': return 2;
case 'G': return 3;
}
}
void insert(const char *s,int v)
{
int u=0;
for (int i=0;s[i]!='\0';i++)
{
int c=idx(s[i]);
if (ch[u][c]==0)
{
memset(ch[sz],0,sizeof ch[sz]);
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
}
void get_fail()
{
int f=0,r=-1;
nex[0]=0;
for (itn c=0;c<maxsize;c++)
{
int u=ch[0][c];
if (u!=0)
{
nex[u]=0;
q[++r]=u;
}
}
while (f<=r)
{
int x=q[f++];
for (int c=0;c<maxsize;c++)
{
int u=ch[x][c];
if (u==0)
{
ch[x][c]=ch[nex[x]][c];
continue;
}
q[++r]=u;
int v=nex[x];
nex[u]=ch[v][c];
val[u]|=val[nex[u]];
}
}
}
int calc(int x,int n)
{
int score=0;
for (int i=0;i<n;i++)
if (x&(1<<i)) score+=w[i];
return score;
}
int go(int l,int n)
{
memset(dp,0,sizeof dp);
dp[0][0][0]=true;
int x=1;
for (int i=1;i<=l;i++,x^=1)
{
memset(dp[x],0,sizeof dp[x]);
for (int j=0;j<sz;j++)
for (int k=0;k<4;k++)
for (int l=0;l<(1<<n);l++)
if (dp[x^1][j][l]) dp[x][ch[j][k]][l|val[ch[j][k]]]=true;
}
int MAX=-1;
for (int i=0;i<(1<<n);i++)
{
int cur=calc(i,n);
if (cur<=MAX) continue;
for (int j=0;j<=sz;j++)
if (dp[x^1][j][i])
{
MAX=cur;
break;
}
}
return MAX;
}
}acauto;
int main()
{
#ifdef FCBRUCE
freopen("/home/fcbruce/code/t","r",stdin);
#endif // FCBRUCE
int n,l;
while (scanf("%d%d",&n,&l)==2)
{
acauto.clear();
for (int i=0;i<n;i++)
{
scanf("%s %d",gene[i],w+i);
acauto.insert(gene[i],1<<i);
}
acauto.get_fail();
int MAX=acauto.go(l,n);
if (MAX>=0) printf("%d\n",MAX);
else puts("No Rabbit after 2012!");
}
return 0;
}
HDU 4057 Rescue the Rabbit (AC自动机+DP)
原文地址:http://blog.csdn.net/u012965890/article/details/41125153