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