ZOJ3545 Rescue the Rabbit
分析
未知定长串中不同已知模板串的出现次数问题,一般做法是AC自动机上dp。
考虑背包,\(dp(i,j,k)\)表示当前串长为\(i\),在AC自动机上对应节点\(j\),已匹配的模板串的状态为\(k\)的情况是否出现。用刷表法向后转移。先枚举不定串长度,再枚举AC自动机上节点,然后枚举已知状态,最后枚举字母边转移。
时间复杂度\(O(l \cdot MaxNode \cdot 2^n \cdot SigmaSize)\)。第一维可以滚动,空间复杂度\(O(MaxNode \cdot 2^n)\)
代码
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x){
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;
const int MAXN=1010;
const int SigmaSize=4;
bool dp[2][MAXN][1100];
int mp[15];
struct Trie
{
int next[MAXN][SigmaSize];
int fail[MAXN];
int end[MAXN];
int root,ncnt;
int newnode()
{
for(int i=0;i<SigmaSize;++i)
next[ncnt][i]=-1;
end[ncnt++]=0;
return ncnt-1;
}
void init()
{
ncnt=0;
root=newnode();
}
int id(char c)
{
if(c=='A')
return 0;
else if(c=='G')
return 1;
else if(c=='T')
return 2;
else
return 3;
}
void insert(char*str,int v)
{
int now=root;
int len=strlen(str);
for(int i=0;i<len;++i)
{
int c=id(str[i]);
if(next[now][c]==-1)
next[now][c]=newnode();
now=next[now][c];
}
end[now]|=(1<<v);
}
void getfail()
{
queue<int>Q;
fail[root]=root;
for(int i=0;i<SigmaSize;++i)
{
if(next[root][i]==-1)
next[root][i]=root;
else
{
fail[next[root][i]]=root;
Q.push(next[root][i]);
}
}
while(!Q.empty())
{
int now=Q.front();
Q.pop();
end[now]|=end[fail[now]];
for(int i=0;i<SigmaSize;++i)
{
if(next[now][i]==-1)
next[now][i]=next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
void solve(int n,int l)
{
memset(dp,0,sizeof(dp));
dp[0][0][0]=1; // dp[len][node][state]
int cur=1;
for(int i=1;i<=l;++i)
{
memset(dp[cur],0,sizeof(cur));
for(int j=0;j<ncnt;++j)
{
for(int k=0;k<(1<<n);++k)
{
for(int q=0;q<SigmaSize;++q)
{
int nxt=next[j][q];
dp[cur][nxt][k|end[nxt]]=(dp[cur][nxt][k|end[nxt]]||dp[cur^1][j][k]);
}
}
}
cur^=1;
}
int ans=-INF;
for(int i=0;i<ncnt;++i)
for(int j=0;j<(1<<n);++j)
{
if(dp[cur^1][i][j])
{
int sum=0;
for(int k=0;k<n;++k)
if(j&(1<<k))
sum+=mp[k];
ans=max(ans,sum);
}
}
if(ans<0)
printf("No Rabbit after 2012!\n");
else
printf("%d\n",ans);
}
}AC;
char s[110];
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n,l,w;
while(~scanf("%d %d",&n,&l))
{
AC.init();
for(int i=0;i<n;++i)
{
scanf("%s %d",s,&w);
AC.insert(s,i);
mp[i]=w;
}
AC.getfail();
AC.solve(n,l);
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
ZOJ3545 Rescue the Rabbit的更多相关文章
- JSOI2009 密码 和 JSOI2007 文本生成器 和 ZOJ3545 Rescue the Rabbit
密码 众所周知,密码在信息领域起到了不可估量的作用.对于普通的登陆口令,唯一的破解 方法就是暴力破解一逐个尝试所有可能的字母组合,但这是一项很耗时又容易被发现的工 作.所以,为了获取对方的登陆口令,在 ...
- HDU-4057 Rescue the Rabbit(AC自动机+DP)
Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu4057 Rescue the Rabbit
地址:http://acm.hdu.edu.cn/showproblem.php?pid=4057 题目: Rescue the Rabbit Time Limit: 20000/10000 MS ( ...
- hdu4057 Rescue the Rabbit(AC自己主动机+DP)
Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU4057 Rescue the Rabbit(AC自动机+状压DP)
题目大概是给几个DNA片段以及它们各自的权值,如果一个DNA包含某个片段那么它的价值就加上这个片段的权值,同时包含多个相同DNA片段也只加一次,问长度l的DNA可能的最大价值. 与HDU2825大同小 ...
- HDU 4057 Rescue the Rabbit(AC自动机+DP)
题目链接 一个数组开小了一点点,一直提示wa,郁闷,这题比上个题简单一点. #include <iostream> #include <cstring> #include &l ...
- ZOJ 3545 Rescue the Rabbit(AC自动机+状压DP)(The 2011 ACM-ICPC Asia Dalian Regional Contest)
Dr. X is a biologist, who likes rabbits very much and can do everything for them. 2012 is coming, an ...
- 【HDOJ】4057 Rescue the Rabbit
挺有意思的一道题目,解法是AC自动机+DP.AC自动机建立fail指针时,一定要注意结点的属性也需要传递.AC自动机结合了trie和kmp的优点.需要注意的是,每个模式串仅计算一次,否则这题很难解. ...
- Zoj 3545 Rescue the Rabbit(ac自己主动机+dp)
标题效果: 鉴于DNA有一个正确的顺序值.请构造一个长度I的DNA在这个序列使DNA正确的顺序值极大.它被认为是负的输出噼啪. .. IDEAS: 施工顺序是,ac己主动机上走,求最大要用到dp dp ...
随机推荐
- boruvka算法
算法正确性证明: 1.最优性:最小边一定包含在生成树中. 2.合法性:一定不会构成环.如果存在环说明一个点的最小连边有两个,显然矛盾. 算法时间复杂度证明: 每执行一次算法,所有联通块的大小都至少为2 ...
- tomcat8w.exe 运行 提示 指定的服务未安装 unable to open the service 'tomcat8'
新下载的Tomcat8 解压版,解压缩完成后,双击tomcat8.exe出现个DOS样子的窗口一闪而过消失了,tomcat也没有启动成功.双击tomcat8w.exe 弹出个错误对话框,说“指定的服务 ...
- 2-20 MySQL集群搭建实现高可用
MySQL集群概述和安装环境 MySQL Cluster是MySQL适合于分布式计算环境的高实用.高冗余版本.Cluster的汉语是"集群"的意思.它采用了NDB Cluster ...
- Oracle 11g dataguard check RTA(real time apply)
Oracle 11g dataguard check RTA(real time apply) 2017年8月24日 16:38 环境:oracle 11.2.0.1 OEL 5.8 注:以下操作都在 ...
- SQL Server日志清空方法
1.清空日志:DUMP TRANSACTION databasename WITH NO_LOG 2.截断事务日志:BACKUP LOG databasename WITH ...
- SQL Server 调优系列基础篇 - 子查询运算总结
前言 前面我们的几篇文章介绍了一系列关于运算符的介绍,以及各个运算符的优化方式和技巧.其中涵盖:查看执行计划的方式.几种数据集常用的连接方式.联合运算符方式.并行运算符等一系列的我们常见的运算符.有兴 ...
- 当前标识没有对“C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files”的写访问权限。
解决方案: PHP程序如果遇到这个问题,请将应用程序池.NET改成无托管代码
- PatePoco中对sql参数化时Top参数化的问题
PatePoco中对sql参数化是直接用@+参数名来处理,但是想用如下语句时竟然报错了 SELECT TOP @num * FROM tableA 执行时抛出异常,根据错误提示搞了很久都没找到原因,最 ...
- git push时候总提示输入账号密码,如何免除设置?
1. 打开.ssh所在目录 home,即C:\Users\Administrator2. 在home中,进入git bash命令终端,创建.git-credentials文件,编辑 touch .gi ...
- http请求报头
客户请求的处理:Http请求报头 创建高效servlet的关键之一,就是要了解如何操纵超文本传输协议(HypeText TransferProtocol, HTTP). HTTP请求报头不同于前一章的 ...