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

------------------------------------------------------------------------------------------------

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
typedef long long ll;
#define b(x) (1 << (x))
#define C(c) (c - 'a')
 
const int maxn = 11;
 
int L, N, Com[maxn][maxn], lth[maxn], V[maxn], R[45], cnt;
ll dp[2][100][b(maxn)];
char S[maxn][maxn], res[45][30];
bool F[maxn];
 
struct Node {
Node *ch[26], *f;
int Id, n;
} pool[100], *pt = pool, *Root, *q[100];
 
void Init() {
scanf("%d%d", &L, &N);
(Root = pt++)->Id = 0;
int idn = Root->n = 0;
for(int i = 0; i < N; i++) {
scanf("%s", S[i]);
lth[i] = strlen(S[i]);
Node* t = Root;
for(int j = 0; j < lth[i]; j++) {
if(!t->ch[C(S[i][j])]) {
pt->Id = ++idn, pt->n = 0;
t->ch[C(S[i][j])] = pt++;
}
t = t->ch[C(S[i][j])];
}
t->n |= b(i);
}
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++) {
int &v = Com[i][j];
for(v = min(lth[i], lth[j]); v; v--) {
bool F = true;
int a = lth[i] - v, b = 0;
while(a < lth[i]) {
if(S[i][a] != S[j][b]) {
F = false;
break;
}
a++, b++;
}
if(F) break;
}
}
cnt = 0;
}
 
void Build() {
int h = 0, t = 0;
(q[t++] = Root)->f = NULL;
while(h < t) {
Node* o = q[h++];
for(int i = 0; i < 26; i++) if(o->ch[i]) {
Node* f = o->f;
while(f && !f->ch[i]) f = f->f;
o->ch[i]->f = f ? f->ch[i] : Root;
q[t++] = o->ch[i];
}
}
}
 
void DFS(int x, int len) {
if(x == N) {
if(len == L) {
int p = 0;
for(int i = 0; i < N; i++)
for(int j = i ? Com[V[i - 1]][V[i]] : 0; j < lth[V[i]]; j++)
res[cnt][p++] = S[V[i]][j];
cnt++;
}
return;
}
for(int i = 0; i < N; i++) if(!F[i]) {
F[V[x] = i] = true;
DFS(x + 1, len + lth[i] - Com[V[x - 1]][i]);
F[i] = false;
}
}
 
bool Cmp(const int &l, const int &r) {
return strcmp(res[l], res[r]) < 0;
}
 
void Work() {
int c = 0, p = 1, h = 0, t = 0, S = b(N) - 1;
q[t++] = Root;
while(h < t) {
Node* o = q[h++];
if(o->f) o->n |= o->f->n;
for(int i = 0; i < 26; i++)
if(o->ch[i]) q[t++] = o->ch[i];
}
memset(dp[c], 0, sizeof dp[c]);
dp[c][0][0] = 1;
for(int i = 0; i < L; i++) {
swap(c, p);
memset(dp[c], 0, sizeof dp[c]);
for(int r = 0; r < t; r++)
for(int s = b(N); s--; ) if(dp[p][q[r]->Id][s]) {
for(int j = 0; j < 26; j++) {
Node* o = q[r];
while(o && !o->ch[j]) o = o->f;
o = o ? o->ch[j] : Root;
dp[c][o->Id][s | o->n] += dp[p][q[r]->Id][s];
}
}
}
ll ans = 0;
for(int i = 0; i < t; i++)
ans += dp[c][q[i]->Id][S];
printf("%lld\n", ans);
if(ans > 42) return;
memset(F, 0, sizeof F);
for(int i = 0; i < N; i++)
F[V[0] = i] = true, DFS(1, lth[i]), F[i] = false;
for(int i = 0; i < ans; i++) 
res[R[i] = i][L] = '\0';
sort(R, R + ans, Cmp);
for(int i = 0; i < ans; i++)
printf("%s\n", res[R[i]]);
}
 
int main() {
Init();
Build();
Work();
return 0;
}

-----------------------------------------------------------------------------------------------

1559: [JSOI2009]密码

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 675  Solved: 213
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

10 2
hello
world

Sample Output

2
helloworld
worldhello

HINT

Source

BZOJ 1559: [JSOI2009]密码( AC自动机 + 状压dp )的更多相关文章

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

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

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

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

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

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

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

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

  5. hdu2825 Wireless Password(AC自动机+状压dp)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission ...

  6. hdu 4057--Rescue the Rabbit(AC自动机+状压DP)

    题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...

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

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

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

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

  9. UVALive - 4126 Password Suspects (AC自动机+状压dp)

    给你m个字符串,让你构造一个字符串,包含所有的m个子串,问有多少种构造方法.如果答案不超过42,则按字典序输出所有可行解. 由于m很小,所以可以考虑状压. 首先对全部m个子串构造出AC自动机,每个节点 ...

随机推荐

  1. 搭建C#框架 博文观感

    最近刚开始着手做项目,在后期开发的时候遇到不少预期之外的问题,而且工期也超出预算不少.反思了一下,主要是做的项目少,前期需求分析不明朗,当然对于框架也没有意识.凡此种种.当然,遇到问题就要去想办法解决 ...

  2. static和extern关键字 对变量的作用

    本文目录 • 一.在Java中,全局变量的定义没有严格的位置规定 • 二.在C语言中,全局变量定义的位置是有限制的 • 三.重复定义同一个变量 • 四.不同源文件中的同名变量 • 五.static关键 ...

  3. Struts2返回Json数据(使用Struts2插件)

    这篇我将介绍如何使用Struts2的struts2-json-plugin.jar插件返回JSON数据. 一.其中主要步骤有: 1.将struts2-json-plugin.jar插件拷贝到项目的&q ...

  4. C趣味100道之58.拉丁方的一些想法。

    题目如上. 思路(未写) 完整代码如下: #include<iostream> #include<queue> #include<math.h> using nam ...

  5. Windows中的对象

    来源  http://www.0xaa55.com/forum.php?mod=viewthread&tid=1401&extra=page%3D1  windows里常用句柄操作资源 ...

  6. git 克隆本地仓库

    如果要从本地仓库克隆到另一个地方使用如下命令 git clone d:/SourceRepository d:/DestinationRepository d:/SourceRepository:本地 ...

  7. Oracle数据库的启动和关闭

    深刻理解Oracle数据库的启动和关闭 Oracle数据库提供了几种不同的数据库启动和关闭方式,本文将详细介绍这些启动和关闭方式之间的区别以及它们各自不同的功能. 一.启动和关闭Oracle数据库 对 ...

  8. 构造HTTP请求Header实现"伪造来源IP"

    构造 HTTP请求 Header 实现“伪造来源 IP ” 在阅读本文前,大家要有一个概念,在实现正常的TCP/IP 双方通信情况下,是无法伪造来源 IP 的,也就是说,在 TCP/IP 协议中,可以 ...

  9. Linux网络管理——TCP/IP四层模型

    1. 网络基础 .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB",&q ...

  10. 精读《javascript高级程序设计》笔记三——面向对象的程序设计

    重点来了,我认为这一章值得好好地反复地看.看第一遍 还是懵懵懂懂,现在看第二遍,终于能看出点意思了. 创建对象 工厂模式 function createPerson(name, age, job){ ...