| ||||||||||
Rescue the RabbitTime Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1487 Accepted Submission(s): 432
Problem Description
Dr. X is a biologist, who likes rabbits very much and can do everything for them. 2012 is coming, and Dr. X wants to take some rabbits to Noah's Ark, or there are no rabbits any more.
A rabbit's genes can be expressed as a string whose length is l (1 ≤ l ≤ 100) containing only 'A', 'G', 'T', 'C'. There is no doubt that Dr. X had a in-depth research on the rabbits' genes. He found that if a rabbit gene contained a particular gene segment, we could consider it as a good rabbit, or sometimes a bad rabbit. And we use a value W to measure this index. We can make a example, if a rabbit has gene segment "ATG", its W would plus 4; and if has gene segment "TGC", its W plus -3. So if a rabbit's gene string is "ATGC", its W is 1 due to ATGC contains both "ATG"(+4) and "TGC"(-3). And if another rabbit's gene string is "ATGATG", its W is 4 due to one gene segment can be calculate only once. Because there are enough rabbits on Earth before 2012, so we can assume we can get any genes with different structure. Now Dr. X want to find a rabbit whose gene has highest W value. There are so many different genes with length l, and Dr. X is not good at programming, can you help him to figure out the W value of the best rabbit.
Input
There are multiple test cases. For each case the first line is two integers n (1 ≤ n ≤ 10),l (1 ≤ l ≤ 100), indicating the number of the particular gene segment and the length of rabbits' genes.
The next n lines each line contains a string DNAi and an integer wi (|wi| ≤ 100), indicating this gene segment and the value it can contribute to a rabbit's W.
Output
For each test case, output an integer indicating the W value of the best rabbit. If we found this value is negative, you should output "No Rabbit after 2012!".
Sample Input
Sample Output
|
题意:构造长度为L的串,使其价值最大
思路:构造AC自动机,dp[i][j][k]表示长度为i,位于Trie树上j节点的,状态为k的能不能达到,然后遍历一边找到最大值,要用滚动数组
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=100010;
const int SIGMA_SIZE=4;
const int INF=100000000;
int N,L;
char s[110];
int dp[2][1010][1<<10];
int value[110];
struct AC
{
int ch[maxn][SIGMA_SIZE],val[maxn];
int fail[maxn];
int sz;
void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;}
int idx(char x)
{
if(x=='A')return 0;
if(x=='T')return 1;
if(x=='G')return 2;
return 3;
}
void insert(char *s,int x)
{
int n=strlen(s);
int u=0;
for(int i=0;i<n;i++)
{
int c=idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]|=(1<<x);
}
void getfail()
{
queue<int> q;
fail[0]=0;
int u=0;
for(int i=0;i<SIGMA_SIZE;i++)
{
u=ch[0][i];
if(u){fail[u]=0;q.push(u);}
}
while(!q.empty())
{
int r=q.front();q.pop();
if(val[fail[r]])val[r]|=val[fail[r]];
for(int c=0;c<SIGMA_SIZE;c++)
{
u=ch[r][c];
if(!u){ch[r][c]=ch[fail[r]][c];continue;}
q.push(u);
int v=fail[r];
while(v&&!ch[v][c])v=fail[v];
fail[u]=ch[v][c];
}
}
}
int cal(int x)
{
int ans=0;
for(int i=0;i<N;i++)
if(x&(1<<i))
ans+=value[i+1];
return ans;
}
void solve()
{
memset(dp,0,sizeof(dp));
dp[0][0][0]=1;
for(int i=1;i<=L;i++)
{
memset(dp[i&1],0,sizeof(dp[i&1]));
for(int j=0;j<sz;j++)
{
for(int r=0;r<(1<<N);r++)
for(int k=0;k<SIGMA_SIZE;k++)
{
int u=ch[j][k];
if(dp[(i+1)&1][j][r])
dp[i&1][u][r|val[u]]=1;
}
}
}
int ans=-INF;
for(int j=0;j<(1<<N);j++)
for(int i=0;i<sz;i++)
if(dp[L&1][i][j])
{
ans=max(ans,cal(j));
break;
}
if(ans>=0)printf("%d\n",ans);
else printf("No Rabbit after 2012!\n");
}
}ac;
int main()
{
while(scanf("%d%d",&N,&L)!=EOF)
{
ac.clear();
int x;
for(int i=1;i<=N;i++)
{
scanf("%s%d",s,&value[i]);
ac.insert(s,i-1);
}
ac.getfail();
ac.solve();
}
return 0;
}