建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. nide.js(二)文件I/O

    文件I/O fs模块的基本用法 node.js中提供一个名为fs的模块来支持I/O操作,fs模块的文件I/O是对标准POSIX函数的简单封装. 1.writeFile函数的基本用法 文件I/O,写入是 ...

  2. Java代码整理

  3. PHP正则提取HTML中img的url值

    <html> <head> <title>获取HTML中的img的src值</title> </head> <body> < ...

  4. PHP中date函数参数详解

    date函数输出当前的时间echo date('Y-m-d H:i:s', time()); // 格式:xxxx-xx-xx xx:xx:xx 第一个参数的格式分别表示: a - "am& ...

  5. Orchard 源码探索(Log)

    简单工厂模式.抽象工厂模式和适配器模式 依赖倒置原则也叫依赖倒转原则,Dependence Inversion Principle,对抽象进行编程,不要对实现进行编程. A.高层次的模块不应该依赖于低 ...

  6. Delphi 编码转换 Unicode gbk big5(使用LCMapString设置区域后,再用API转换)

    原文:http://blog.dream4dev.com/article.asp?id=17 function UnicodeEncode(Str: string; CodePage: integer ...

  7. mojo 接口示例

    <pre name="code" class="python">use Mojolicious::Lite; use JSON qw/encode_ ...

  8. CentOS7 vs centos6

    The CentOS Project has announced general availability of CentOS-7, the first release of the free Lin ...

  9. JAVA代码静态检测之PMD

    今天再次想启动Java代码静态检测工具的利用问题,主要再次尝试用了PMD,发现不少代码编码规范问题和好的代码建议,并学到不少自己之前没有注意到的Java方便的基础知识,感觉很不错,把相关明白的好的规则 ...

  10. Java面试题之六

    三十一.如何取小数点前两位,并四舍五入. package com.lovo; public class TestDot2 { // 方法1 public void test1(double c) { ...