计蒜客-蒜场抽奖(AC自动机+状态压缩DP)


题解:题意不再说了,题目很清楚的。
思路:因为N<=10,所以考虑状态压缩 AC自动机中 val[1<<i]: 表示第i个字符串。AC自动机中fail指针是指当前后缀在其他串里面所能匹配的最长前缀的长度,然后我们在这里统计一下以该点结束所能包含的字符串的数量(就是在fail树中该点到根节点所经过的所有为单词结尾的点,在这里我们只要val[x] |= val[fail[x]]就行了,因为val[fail[x]]已经统计过 点fail[x]到根的值了)。
考虑dp[i][j][k]:表示长度为i,第j个状态点,k为包含的单词的状态, 是否存在。然后转移方程为:if( ch[m-1][j][k] ) ch[m][ ch[j][ char ] ][ k|val[ ch[j][char] ] ]=1;(char : 为第j个状态再往后走一步到达的状态);
我们的长度是一步一步走的,而且当前步数,仅有上一步确定,所以我们可以压缩步数为奇数偶数,变为:if( ch[ (m-1)&1 ][j][k] ) ch[ m&1 ][ ch[j][ char ] ][ k|val[ ch[j][char] ] ]=1;最后我们只要在第m步的每个状态包含不停字符串状态时的答案里面去最大值就行了。
参考代码:
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=;
int ch[maxn][],val[maxn],fail[maxn];
int w[],tot,n,m,Ans[maxn];
bool dp[][maxn][<<];
char s[]; void Init()
{
tot=;
memset(val,,sizeof val);
memset(ch[tot],,sizeof ch[tot]);
} void Insert(char *s,int x)
{
int len=strlen(s),u=;
for(int i=;i<len;++i)
{
int c=s[i]-'a';
if(!ch[u][c]) {ch[u][c]=tot++;memset(ch[tot],,sizeof ch[tot]);}
u=ch[u][c];
}
val[u]=<<x;
} void GetFail()
{
queue<int>q;
for(int i=;i<;++i)
if(ch[][i]) q.push(ch[][i]);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=;i<;++i)
{
int v=ch[u][i];
if(!v){ch[u][i]=ch[fail[u]][i];continue;}
q.push(v);
fail[v]=ch[fail[u]][i];
val[v]|=val[fail[v]];
}
}
} void Work()
{
dp[][][]=;
for(int i=;i<=m;++i)
{
memset(dp[i&],,sizeof dp[i&]);
for(int j=;j<tot;++j)
for(int k=;k<;++k)
for(int z=;z<(<<n);++z)
{
if(dp[(i-)&][j][z])
dp[i&][ch[j][k]][z|val[ch[j][k]]]=;
}
}
} int GetAns(int x)
{
int ans=;
for(int i=;i<n;++i)
if(x&(<<i)) ans+=w[i];
return ans;
} int main()
{
scanf("%d%d",&n,&m);
Init();
for(int i=;i<n;++i)
scanf("%s%d",s,w+i),Insert(s,i);
GetFail();
Work();
int res=-INF; for(int j=;j<(<<n);++j) Ans[j]=GetAns(j);
for(int i=;i<tot;++i)
for(int j=;j<(<<n);++j)
if(dp[m&][i][j]) res=max(res,Ans[j]); if(res<) puts("Unhappy!");
else printf("%d\n",res); return ;
}
计蒜客-蒜场抽奖(AC自动机+状态压缩DP)的更多相关文章
- HDU 4511 (AC自动机+状态压缩DP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4511 题目大意:从1走到N,中间可以选择性经过某些点,比如1->N,或1->2-> ...
- POJ 3691 (AC自动机+状态压缩DP)
题目链接: http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...
- hdu 4057(ac自动机+状态压缩dp)
题意:容易理解... 分析:题目中给的模式串的个数最多为10个,于是想到用状态压缩dp来做,它的状态范围为1-2^9,所以最大为2^10-1,那我们可以用:dp[i][j][k]表示长度为i,在tri ...
- bzoj1195 神奇的ac自动机+状态压缩dp
/* 难的不是ac自动机,是状态压缩dp 之前做了一两题类似题目,感觉理解的还不够透彻 */ #include<iostream> #include<cstdio> #incl ...
- HDU 4758 Walk Through Squares( AC自动机 + 状态压缩DP )
题意:给你两个串A,B, 问一个串长为M+N且包含A和B且恰好包含M个R的字符串有多少种组合方式,所有字符串中均只含有字符L和R. dp[i][j][k][S]表示串长为i,有j个R,在自动机中的状态 ...
- HDU 4057 Rescue the Rabbit ( AC自动机 + 状态压缩DP )
模板来自notonlysuccess. 模式串只有10个,并且重复出现的分值不累加,因此很容易想到状态压缩. 将模式串加入AC自动机,最多有10*100个状态. dp[i][j][k]:串长为i,在T ...
- hdu 2825(ac自动机+状态压缩dp)
题意:容易理解... 分析:在做这道题之前我做了hdu 4057,都是同一种类型的题,因为题中给的模式串的个数最多只能为10个,所以我们就很容易想到用状态压缩来做,但是开始的时候我的代码超时了dp时我 ...
- 计蒜客 疑似病毒 (AC自动机 + 可达矩阵)
链接 : Here! 背景 : 开始我同学是用 AC自动机 + DP 的方法来做这道题, 这道题的标签是 AC自动机, 动态规划, 矩阵, 按道理来说 AC自动机 + DP 应该是能过的, 但是他不幸 ...
- 【bzoj1195】[HNOI2006]最短母串 AC自动机+状态压缩+BFS最短路
原文地址:http://www.cnblogs.com/GXZlegend/p/6825226.html 题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串 ...
随机推荐
- Vue基础系列(四)——Vue中的指令(上)
写在前面的话: 文章是个人学习过程中的总结,为方便以后回头在学习. 文章中会参考官方文档和其他的一些文章,示例均为亲自编写和实践,若有写的不对的地方欢迎大家和我一起交流. VUE基础系列目录 < ...
- hashMapp
原文链接:https://www.iteye.com/topic/539465 Hashmap是一种非常常用的.应用广泛的数据类型,最近研究到相关的内容,就正好复习一下.网上关于hashmap的文章很 ...
- C# VI: 删除字符串中指定字符的几种方法
本文基于Stackoverflows上以下几个Question: Fastest way to remove chars from string (http://stackoverflow.com/q ...
- 一文带你深入了解 Redis 的持久化方式及其原理
Redis 提供了两种持久化方式,一种是基于快照形式的 RDB,另一种是基于日志形式的 AOF,每种方式都有自己的优缺点,本文将介绍 Redis 这两种持久化方式,希望阅读本文后你对 Redis 的这 ...
- 通过myclipse建立一个简单的Hibernate项目(PS:在单元测试中实现数据的向表的插入)
Hibernate的主要功能及用法: Ⅰ.Hibernate封装了JDBC,使Java程序员能够以面向对象的思想对数据库进行操作 Ⅱ.Hibernate可以应用于EJB的J2EE架构,完成数据的持久化 ...
- nyoj 72-Financial Management (求和 ÷ 12.0)
72-Financial Management 内存限制:64MB 时间限制:3000ms 特判: No 通过数:7 提交数:12 难度:1 题目描述: Larry graduated this ye ...
- python获取随机验证码或者下发激活码
http://stackoverflow.com/questions/2823316/generate-a-random-letter-in-python >>> import ra ...
- 🔥《手把手》系列基础篇之2-python+ selenium-打开和关闭浏览器(详细)
1. 简介 本节介绍如何初始化一个webdriver实例对象driver,然后打开和关闭firefox浏览器.要用selenium打开fiefox浏览器.首先需要去下载一个driver插件geckod ...
- Excel 如何做不定长区间汇总统计
第一步:创建数据-区间 辅助表(注意:首列值必须以升序排列,为后面vlookup模糊匹配做准备) 第二步:用vlookup模糊匹配生成一个新的“金额区间”字段 第三步:以“金额区间”字段为行透视汇总
- 选择了uniapp开发app
7月份打算做一简单app,之前公司做app的时候简单用过Dcloud公司的mui,当时由于uniapp刚出来,最终选择了mui.对uniapp的 了解几乎没有. 做app对我来说几乎是零基础的,当然是 ...