题目链接

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
2 4
ATG 4
TGC -3
1 6
TGC 4
4 1
A -1
T -2
G -3
C -4
 
Sample Output
4
4
No Rabbit after 2012!

 
Hint

case 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.
 
题意:现在有n个基因片段(用包含A、G、T、C的字符串表示),每个基因片段有一个权值,现在求长为L的基因的最大权值(每个基因片段重复出现算一次,不用计算多次)?
 
思路:AC自动机+状态压缩DP,dp[i][j][s]表示长为 i 的基因且在AC自动机 tire树上匹配到节点 j 时包含基因片段集合为 s 时合法(即dp[i][j][s]=1,如果等于0 则表示不存在这样的基因),那么由长为 i 的字符串可以递推到长为 i+1 的字符串基因, x=node[j].son[k]->id 和  f=node[j].son[k]->flag => dp[i+1][x][s|f]=1  (0<=k<=3), 最后计算长为L的基因最大权值和,根据dp[L][j][s] 遍历所有节点的所有状态,计算每个状态下的权值和,得到最大权值和。
 
注意:dp每次根据前一长度下的状态 推 下一长度下的状态,那么可以使用滚动数组减小存储空间。
 
代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <string>
using namespace std;
const int N=;
int a[],tot;
struct Node
{
Node *fail;
Node *son[];
int flag;
int id;
}node[N],*root;
queue<Node*>Q;
bool dp[][N][]; int f(char c)
{
if(c=='A') return ;
if(c=='G') return ;
if(c=='T') return ;
if(c=='C') return ;
}
void insert(string s,int id)
{
Node *now=root;
for(int i=;i<s.length();i++)
{
int x=f(s[i]);
if(now->son[x]==NULL) now->son[x]=&node[tot++];
now=now->son[x];
}
now->flag|=(<<(id-));
}
void build()
{
Q.push(root);
while(!Q.empty())
{
Node *now=Q.front(); Q.pop();
for(int i=;i<;i++)
{
if(now->son[i])
{
Node *p=now->fail;
while(p&&(!(p->son[i]))) p=p->fail;
now->son[i]->fail=(p)?(p->son[i]):root;
now->son[i]->flag|=now->son[i]->fail->flag;
Q.push(now->son[i]);
}
else now->son[i]=(now!=root)?now->fail->son[i]:root;
}
}
}
void init()
{
tot=;
root=&node[];
memset(dp,,sizeof(dp));
while(!Q.empty()) Q.pop();
for(int i=;i<N;i++)
{
node[i].fail=NULL;
node[i].flag=;
node[i].id=i;
for(int j=;j<;j++) node[i].son[j]=NULL;
}
}
int main()
{
int n,l;
while(scanf("%d%d",&n,&l)!=EOF)
{
init();
for(int i=;i<=n;i++)
{
string s; cin>>s;
insert(s,i);
scanf("%d",&a[i]);
}
build();
dp[][][]=;
int cn=;
for(int i=;i<l;i++)
{
cn^=;
memset(dp[cn],,sizeof(dp[cn]));
for(int j=;j<tot;j++)
{
for(int s=;s<(<<n);s++)
{
if(!dp[cn^][j][s]) continue;
for(int k=;k<;k++)
{
int x=node[j].son[k]->id;
int f=node[j].son[k]->flag;
dp[cn][x][s|f]=;
}
}
}
}
int ans=-;
for(int i=;i<tot;i++)
{
for(int s=;s<(<<n);s++)
{
if(!dp[cn][i][s]) continue;
int tmp=;
int x=s;
for(int k=;k<=n;k++)
{
if(x&) tmp+=a[k];
x>>=;
}
ans=max(ans,tmp);
}
}
if(ans<) puts("No Rabbit after 2012!");
else printf("%d\n",ans);
}
return ;
}

hdu 4057--Rescue the Rabbit(AC自动机+状压DP)的更多相关文章

  1. HDU 4057 Rescue the Rabbit ( AC自动机 + 状态压缩DP )

    模板来自notonlysuccess. 模式串只有10个,并且重复出现的分值不累加,因此很容易想到状态压缩. 将模式串加入AC自动机,最多有10*100个状态. dp[i][j][k]:串长为i,在T ...

  2. zoj3545Rescue the Rabbit (AC自动机+状压dp+滚动数组)

    Time Limit: 10 Seconds      Memory Limit: 65536 KB Dr. X is a biologist, who likes rabbits very much ...

  3. HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解

    题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...

  4. hdu 6086 -- Rikka with String(AC自动机 + 状压DP)

    题目链接 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, s ...

  5. HDU 2825 Wireless Password(AC自动机 + 状压DP)题解

    题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个 思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上. 代码: #include<cmath> ...

  6. HDU 4057 Rescue the Rabbit(AC自动机+DP)

    题目链接 一个数组开小了一点点,一直提示wa,郁闷,这题比上个题简单一点. #include <iostream> #include <cstring> #include &l ...

  7. HDU - 2825 Wireless Password (AC自动机+状压DP)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2825 题意:给一些字符串,构造出长度为n的字符串,它至少包含k个所给字符串,求能构造出的个数. 题解: ...

  8. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  9. BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】

    题目链接 BZOJ1559 题解 考虑到这是一个包含子串的问题,而且子串非常少,我们考虑\(AC\)自动机上的状压\(dp\) 设\(f[i][j][s]\)表示长度为\(i\)的串,匹配到了\(AC ...

随机推荐

  1. 设计模式-单体模式(C++)

    设计模式-单体模式 单体模式在使用非常方便,适合于单一的对象,例如全局对象的抽象使用. 需要注意的是单体模式不可继承 // 实现 Singleton.h #ifndef __SINGLETON_H__ ...

  2. 看懂c/c++ 函数、指针、数组定义

    读懂 函数 + 指针 + 数组 c语言运算符机器优先级,看这里 结合运算符优先级,我们试着读懂函数和指针 优先级简单看 表达式提升():一级优先 函数():二级优先 数组[]:二级优先 指针定义*:三 ...

  3. sudoku--设想

    在查阅了一些资料和自己动手写一写后,找到一种可行的解法. 第一步 首先将9x9的数独方格分成九份3x3的九宫格,如下图 B1 B2 B3 B4 B5 B6 B7 B8 B9 而后在左上角的B1上随机生 ...

  4. 【Alpha】——First scrum Meeting

    一.今日站立式会议照片 二.每个人的工作 成员 昨天已完成的工作 今天计划完成的工作 · 李永豪 编写测试计划 学习JAVA编程及UI设计 · 郑靖涛 Alpha任务分配计划 学习JAVA编程及UI设 ...

  5. Java-反射机制学习

    反射机制是Java的一个重要性,它使得Java语言具有了动态特性.比如说,可以在代码中动态地获取某个类的信息,生成它的实例.获取其成员变量.调用它的方法.下面通过几个示例来演示反射机制的作用与用法. ...

  6. 201521123017 《Java程序设计》第10周学习总结

    1. 本周学习总结 2. 书面作业 Q1.finally 题目4-2 1.1 截图你的提交结果(出现学号) 1.2 4-2中finally中捕获异常需要注意什么? 1.1 截图 1.2 4-2中fin ...

  7. 201521123103 《java学习笔记》 第十二周学习总结

    一.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 二.书面作业 将Student对象(属性:int id, String name,int age,double ...

  8. 201521123108《Java程序设计》第14周学习总结

    1. 本周学习总结 2. 书面作业 Q1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己的学号.姓名) 答: 在自己建立的数据库上执行常见SQL语句(截 ...

  9. Eclipse rap 富客户端开发总结(12) :Rap 优化之组件的销毁

    一.概述      经过几个月的rap 项目实战,总结了一些小经验,在这里总结一下,希望对大家有所帮助. 二.销毁的处理       相信学习rap 的同学都知道,swt 中提供了许多的组件,像lab ...

  10. json中关于jo.[]中字符串一致的问题

    procedure TForm1.btn1Click(Sender: TObject);var jo:ISuperObject; Temp:string; temp1:Boolean;begin  j ...