沉迷AC自动机无法自拔之:[UVALive 4126] Password Suspects
图片加载可能有点慢,请跳过题面先看题解,谢谢



一看到这么多模式串就非常兴奋,又是\(AC\)自动机
题目就是要求:经过 \(n\) 个节点,把所有单词都遍历一遍的方案数,和那道题差不多嘛
所以这样设:\(f[i][j][k]\) 为,走了 \(i\) 个节点,当前点在 \(j\),单词的经过情况为 \(k\)(一个二进制数)时的方案数
答案很显然是:\(\sum_{i=1}^{size}f[n][i][(1<<m)-1]\)
转移也很显然:\(f[i+1][Son][s|val[Son]]+=f[i][j][s]\)
$
$
但是这道题有点麻烦的就是,它需要输出方案,上面那样子做不太好记录路径
这里考虑反过来搞,这样转移:\(f[i][j][s]+=f[i+1][Son][s|val[Son]]\),答案就变成了\(f[0][0][0]\)
这样做的话,就可以保证只有在有效路径上,\(f\) 值才不为\(0\),那么方案就很好办了
$
$
//made by Hero_of_Someone
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<set>
#define ll long long
using namespace std;
int t,n,m;
struct Trie{
char o[26];
int root,size;
ll f[26][110][1<<10];
int son[110][30],fail[110],val[110];
void init(){
size=1; root=0;
memset(son,0,sizeof(son));
memset(val,0,sizeof(val));
memset(fail,0,sizeof(fail));
memset(f[n],0,sizeof(f[n]));
}
int idx(char c){ return c-'a'; }
void insert(char* s,int v){
int cur=root;
for(int i=0;s[i];i++){
int id=idx(s[i]);
if(!son[cur][id]) son[cur][id]=size++;
cur=son[cur][id];
}
val[cur]|=1<<v; return ;
}
void build(){
int que[110];
int hd=0,tl=0;
for(int i=0;i<26;i++)
if(son[root][i]){
fail[son[root][i]]=root;
que[tl++]=son[root][i];
}
else son[root][i]=root;
while(hd<tl){
int cur=que[hd++];
for(int i=0;i<26;i++){
int Son=son[cur][i];
if(Son){
int f=fail[cur];
while(f && !son[f][i]) f=fail[f];
fail[Son]=son[f][i];
val[Son]|=val[fail[Son]];
que[tl++]=Son;
}
else son[cur][i]=son[fail[cur]][i];
}
}
}
ll dp(){
for(int i=0;i<size;i++) f[n][i][(1<<m)-1]=1;
for(int i=n-1;i>=0;i--)
for(int j=0;j<size;j++)
for(int s=0;s<(1<<m);s++){
f[i][j][s]=0;
for(int k=0;k<26;k++){
int Son=son[j][k];
int ss=s|val[Son];
f[i][j][s]+=f[i+1][Son][ss];
}
}
return f[0][0][0];
}
void print(int i,int j,int s){
if(i==n){
for(int k=0;k<n;k++) printf("%c",o[k]);
puts("");
return ;
}
for(int k=0;k<26;k++){
int Son=son[j][k];
int ss=s|val[Son];
if(f[i+1][Son][ss]){
o[i]=k+'a';
print(i+1,Son,ss);
}
}
}
}AC;
set<string>map;
void init(){
AC.init(),map.clear();
int cnt=0;
for(int i=0;i<m;i++){
char s[15];
scanf("%s",s);
string S=s;
if(!map.count(S)){
AC.insert(s,cnt++);
map.insert(S);
}
}
m=cnt;
}
void work(){
AC.build();
ll ans=AC.dp();
printf("Case %d: %lld suspects\n",++t,ans);
if(ans<=42) AC.print(0,0,0);
}
int main(){ while(scanf("%d%d",&n,&m)&&n){ init(); work(); } return 0; }
沉迷AC自动机无法自拔之:[UVALive 4126] Password Suspects的更多相关文章
- 沉迷AC自动机无法自拔之:[BZOJ2434] [Noi2011] 阿狸的打字机
如标题所言,我已经沉迷于AC自动机无法自拔了... 这又是一道AC自动的题,红红火火恍恍惚惚 这题目做起来真舒服 简单概括一下:\(AC\)自动机\(fail\)树上树链剖分\(+\)树状数组 这种类 ...
- 沉迷AC自动机无法自拔之:穿越广场 square
如标题所言,我已经沉迷于AC自动机无法自拔了... 这又是一道AC自动的题,红红火火恍恍惚惚 穿越广场 [问题描述] L 国的仪仗队要穿越首都广场了.首都广场可以看做是一块 N*M 的矩形网格,仪仗队 ...
- 沉迷AC自动机无法自拔之:[UVA 11468] Substring
图片加载可能有点慢,请跳过题面先看题解,谢谢 这个鬼题目,上一波套路好了 先用题目给的模板串建\(AC\)自动机,把单词结尾标记为 \(val=1\),然后在建好的\(AC\)自动机上跑 \(dp\) ...
- UVALive - 4126 Password Suspects (AC自动机+状压dp)
给你m个字符串,让你构造一个字符串,包含所有的m个子串,问有多少种构造方法.如果答案不超过42,则按字典序输出所有可行解. 由于m很小,所以可以考虑状压. 首先对全部m个子串构造出AC自动机,每个节点 ...
- LA 4126 Password Suspects
问题描述:给定m个模式串,计数包含所有模式串且长度为n的字符串的数目. 数据范围:模式串长度不超过10,m <= 10, n <= 25,此外保证答案不超过1015. 分析:既然要计数给定 ...
- DP(记忆化搜索) + AC自动机 LA 4126 Password Suspects
题目传送门 题意:训练指南P250 分析:DFS记忆化搜索,范围或者说是图是已知的字串构成的自动机图,那么用 | (1 << i)表示包含第i个字串,如果长度为len,且st == (1 ...
- UVALive 4670 Dominating Patterns --AC自动机第一题
题意:多个模板串,一个文本串,求出那些模板串在文本串中出现次数最多. 解法:AC自动机入门模板题. 代码: #include <iostream> #include <cstdio& ...
- UVALive - 3490 Generator (AC自动机+高斯消元dp)
初始有一个空串s,从前n个大写字母中不断随机取出一个字母添加到s的结尾,出现模式串t时停止,求停止时s的长度期望. 这道题解法不唯一,比较无脑的方法是对模式串t建一个单串AC自动机,设u为自动机上的一 ...
- UVALive 4670 Dominating Patterns (AC自动机)
AC自动机的裸题.学了kmp和Trie以后不难看懂. 有一些变化,比如0的定义和f的指向,和建立失配边,以及多了后缀连接数组last.没有试过把失配边直接当成普通边(一开始还是先这样写吧). #inc ...
随机推荐
- SS、SP、BP寄存器
SS, SP, BP 三个寄存器 SS:存放栈的段地址: SP:堆栈寄存器SP(stack pointer)存放栈的偏移地址; BP: 基数指针寄存器BP(base pointer)是一个寄存器,它的 ...
- 03-Maven坐标管理
1.什么是坐标? 2.坐标的详细概念 3.Maven包引用
- jupyter notebook的两个使用技巧
1.设置jupyter notebook的密码: Jupyter-notebook password 2.查看jupyter notebook的token: Jupyter notebook list
- SAP函数 LAST_DAY_OF_MONTHS 获取月末最后一天日期
DATA LAST_DATE TYPE SY-DATUM. CALL FUNCTION 'LAST_DAY_OF_MONTHS' EXPORTING day_in = sy-datum IMPORTI ...
- net 表格控件
一个开源的表格控件,界面像Excel,看来很好,有机会在项目中使用:ReoGrid https://reogrid.net/
- 20155325 Exp2 后门原理与实践
基础问答 例举你能想到的一个后门进入到你系统中的可能方式? 乱点链接 学电脑小白不正确配置电脑 下载非官网软件 例举你知道的后门如何启动起来(win及linux)的方式? 软件:ncat socat ...
- Luogu P2055 [ZJOI2009]假期的宿舍
一道网络有关的问题,还是一句话 网络流重在建模! 这里主要讲两种算法. 1.二分图匹配: 分析题意,我们可以知道题目要求是让所有留在学校的人都能有床睡 而 所有留在学校的人=本校不回家的人+外校的人: ...
- 蒙特卡罗方法 python 实现
蒙特卡罗(Monte Carlo)方法的精髓:用统计结果去计算频率,从而得到真实值的近似值. 一.求圆周率的近似值,采用 投点法 import numpy as np import matplotli ...
- HTML基础之JS
HTML中的三把利器的JS 又称为JavaScript,看着好像和Java有点联系,实际上他和java半毛钱关系都没有,JavaScript和我们学习的Python.Go.Java.C++等,都是一种 ...
- 项目 - RM 部署上centos7 之后出现的一些问题和解决方法
系统版本: [root@localhost logs]# cat /etc/redhat-release CentOS Linux release (Core) 获取方法来自:https://www. ...