题面

bzoj

luogu

首先看到这题就知道随便暴枚

只要是多项式算法都能过

先常规建AC自动机

注意被别的单词包含的单词没有存在的价值

剩余单词状压

大力dp f[长度][节点编号][状态]

\(ans = \sum f[m][i][S]\)

这里把题面的l换成m了 表示密码长度

如果方案数小于等于42的话

说明这个密码是给定词拼成的 不会有自由字母

那么就逆向找到转移到它的状态 记录密码就好啦

注意比较那里原来写的是

if(x.s[i] > y.s[i]) return 1;

显然这样是不行的啊qvq

#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <complex>
#include <ctime>
#include <vector>
#include <queue>
#include <bitset>
#define mp(x, y) make_pair(x, y)
using namespace std;
const int N = 12;
const int M = 102;
const int Sig = 26;
int m, n, acsize, vsize, S;
int en[N], c[M], val[M];
long long ans, f[26][M][(1 << 10) + 5]; struct STR{
char s[30];
void print(){s[m + 1] = '\0'; printf("%s\n", s + 1);}
friend bool operator <(STR x, STR y){
for(int i = 1; i <= m; ++i)
if(x.s[i] != y.s[i]) return x.s[i] > y.s[i];
return 0;
}//大于
}stk;
vector<STR> str; struct AC{
int ch[M][Sig], fail[M];
queue<int> que;
void ins(char* ss, int id){
int now = 0, len = strlen(ss + 1);
for(int i = 1, cc; i <= len; ++i){
cc = ss[i] - 'a';
if(!ch[now][cc]) ch[now][cc] = ++acsize;
now = ch[now][cc]; c[now] = cc;
}
en[id] = now, val[now] = 1;
}
void build(){
int now = 0;
for(int i = 0; i < Sig; ++i) if(ch[0][i]) que.push(ch[0][i]);
while(!que.empty()){
int fro = que.front(); que.pop();
for(int i = 0; i < Sig; ++i){
if(ch[fro][i]) fail[ch[fro][i]] = ch[fail[fro]][i], que.push(ch[fro][i]);//!!
else ch[fro][i] = ch[fail[fro]][i];
}
}
for(int i = 0; i <= acsize; ++i) val[fail[i]] = 0;
for(int i = 0; i <= acsize; ++i) if(val[i])
val[i] = (1 << vsize), ++vsize;
S = (1 << vsize) - 1;
}
void DP(){
f[0][0][0] = 1;
for(int i = 0; i < m; ++i)
for(int j = 0; j <= acsize; ++j)
for(int k = 0; k <= S; ++k) if(f[i][j][k]){
for(int t = 0; t < Sig; ++t){
f[i + 1][ch[j][t]][k | val[ch[j][t]]] += f[i][j][k];
// printf("%d %d %d %lld\n", i, j, k, f[i + 1][ch[j][t]][k | val[ch[j][t]]]);
}
}
}
}ac; void dfs(int x, int cur, int y, int z){
stk.s[x] = z + 'a';
if(x == 1){str.push_back(stk); return ;}
for(int i = 0; i <= acsize; ++i)
if(f[x - 1][i][y] > 0 && ac.ch[i][z] == cur)
dfs(x - 1, i, y, c[i]);
if(val[cur])
for(int i = 0; i <= acsize; ++i)
if(f[x - 1][i][y ^ val[cur]] > 0 && ac.ch[i][z] == cur)
dfs(x - 1, i, y ^ val[cur], c[i]);
} int main(){
scanf("%d%d", &m, &n);
char ss[N];
for(int i = 1; i <= n; ++i){
scanf("%s", ss + 1);
ac.ins(ss, i);
}
ac.build();
ac.DP(); for(int i = 0; i <= acsize; ++i)
ans += f[m][i][S];
printf("%lld\n", ans);
if(ans > 42) return 0; for(int i = 0; i <= acsize; ++i)
if(f[m][i][S]) dfs(m, i, S, c[i]);
sort(str.begin(), str.end());
while(!str.empty()){
(str.back()).print(); str.pop_back();
}
return 0;
}


[JSOI2009]密码 [AC自动机]的更多相关文章

  1. BZOJ 1559: [JSOI2009]密码( AC自动机 + 状压dp )

    建AC自动机后, dp(x, y, s)表示当前长度为x, 在结点y, 包括的串的状态为s的方案数, 转移就在自动机上走就行了. 对于输出方案, 必定是由给出的串组成(因为<=42), 所以直接 ...

  2. BZOJ1559[JSOI2009]密码——AC自动机+DP+搜索

    题目描述 输入 输出 样例输入 10 2 hello world 样例输出 2 helloworld worldhello 提示 这题算是一个套路题了,多个串求都包含它们的长为L的串的方案数. 显然是 ...

  3. [BZOJ1559][JSOI2009]密码(AC自动机)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1559 2009年的省选题虽然比起现在简单了不少,但对我来说还是很有挑战性的. 首先对于这种多串匹配问 ...

  4. [BZOJ1559]密码 AC自动机+状压

    问题 K: [JSOI2009]密码 时间限制: 1 Sec  内存限制: 64 MB 题目描述 众所周知,密码在信息领域起到了不可估量的作用.对于普通的登陆口令,唯一的破解 方法就是暴力破解一逐个尝 ...

  5. 【BZOJ4327】JSOI2012 玄武密码 AC自动机

    [BZOJ4327]JSOI2012 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香 ...

  6. BZOJ4327 [JSOI2012] 玄武密码 [AC自动机]

    题目传送门 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神 ...

  7. Vijos P1951 玄武密码 (AC自动机)

    描述 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在 ...

  8. TZOJ 5986 玄武密码(AC自动机)

    描述 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在 ...

  9. BZOJ 4327 [JSOI2012]玄武密码 (AC自动机)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4327 题解: 做法挺显然,建出AC自动机之后在上面跑,标记所有走过的点,然后再进行递推 ...

随机推荐

  1. C# winForm 窗口跳转后关闭上一个窗口的方法

    FrmMain main = new FrmMain(); main.Owner = this; this.Hide(); main.ShowDialog(); Application.ExitThr ...

  2. Redis Cluster搭建高可用Redis服务器集群

    一.Redis Cluster集群简介 Redis Cluster是Redis官方提供的分布式解决方案,在3.0版本后推出的,有效地解决了Redis分布式的需求,当一个节点挂了可以快速的切换到另一个节 ...

  3. Dubbo和Spring Cloud微服务架构'

    微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然微服务架构没有公认的技术标准和规范或者草案,但业 ...

  4. Spring Cloud项目之断路器集群监控Hystrix Dashboard

    微服务(Microservices Architecture)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独立部署,各个微服务之间是松耦合的.每个微服务仅关注于完 ...

  5. 关于Android中ION的libion

    在高通的OpenCL SDK中,其Android.mk文件中,有判断当前kernel的版本,如果大于4.12,那么就使用libion.so,否则则使用ion kernle uapi: # Tries ...

  6. (最完美)MIUI12系统的Usb调试模式在哪里开启的步骤

    当我们使用安卓手机通过数据线链接到Pc的时候,或者使用的有些app比如我们公司营销小组当使用的app引号精灵,之前的老版本就需要开启usb调试模式下使用,现当新版本不需要了,如果手机没有开启usb调试 ...

  7. 3Delight NSI: A Streamable Render API

    3Delight是应用于高端电影级别渲染的软件渲染器,迄今为止已经参与了无数的电影制作,具体可以参见链接. 如果你对3Delight的印象就依然是RenderMan的替代品,那就显然已经和时代发展脱节 ...

  8. netstat -an查看到大量的TIME_WAIT状态的解决办法

    netstat下time_wait状态的tcp连接: 1.这是一种处于连接完全关闭状态前的状态: 2.通常要等上4分钟(windows server)的时间才能完全关闭: 3.这种状态下的tcp连接占 ...

  9. 从0开始的Python学习011模块

    简介 你已经学习了如何在你的程序中定义一次函数而重用代码.如果你想要在其他程序中重用很多函数,那么你该如何编写程序呢?你可能已经猜到了,答案是使用模块.模块基本上就是一个包含了所有你定义的函数和变量的 ...

  10. DataGuard 单实例到RAC搭建

    背景简介: 本文为针对一次windows平台RAC数据库迁移至Linux平台RAC的笔记,基本步骤为: 1.搭建windows RAC到Linux 单实例数据库的DataGuard 2.做switch ...