建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. 个人封装的一个Camera类

    好久不写博客了,代码写了不少,但大多数都是拿来主义,要不是网上,要不就是自己曾经的代码拼装. 新工作是搞Android开发的,近期任务要求我封装一个Carmera类,自己也认为还是封装以后方便使用,弄 ...

  2. 垃圾回收算法简单介绍——JVM读书笔记&lt;二&gt;

    垃圾回收的过程主要包含两部分:找出已死去的对象.移除已死去的对象. 确定哪些对象存活有两种方式:引用计数算法.可达性分析算法. 方案一:引用计数算法 给对象中加入一个引用计数器.每当有一个地方引用它时 ...

  3. 怎样安装pip--python的包管理工具

    pip是python的包管理工具,使用它来安装python的模块很方便. pip支持的操作系统:Unix/Linux, OS X, and Windows. 支持的python版本号:2.6, 2.7 ...

  4. C#去掉字符串中的汉字

    string str = "测试一下ilove中国so结束"; Regex reg = new Regex(@"[\u4e00-\u9fa5]"); Label ...

  5. uva12589

    题目大意:给n(n<=50)个向量(xi,yi) (0<=xi<=yi<=50),选出其中k(1<=k<=n)个,从(0,0)点开始,依次首尾相连,求此k个向量与x ...

  6. 学习python 一些错误记录

    1. TypeError: 'unicode' object is not callable当遇到这样的错误时候, 一般是属性当做方法调用了,比如,selenium 脚本, driver.title ...

  7. Android 通知栏系列....

    转:http://blog.csdn.net/vipzjyno1/article/details/25248021 在android的应用层中,涉及到很多应用框架,例如:Service框架,Activ ...

  8. mysql函数操作(3)

    <?php $dbh = new PDO('mysql:dbname=testdb;host=localhost', 'mysql_user', 'mysql_pwd'); $dbh->s ...

  9. Siverlight+WCF+Nhibernate 开发之旅(一)

    最近正在开发sl程序,考虑了很久,参考了一些框架,令人头疼的数据访问层最终选择wcf+nhibernate,至于为什么选择wcf和nh,个人参考了其他的框架感觉这两者结合从开发效率和便捷性方面比其他的 ...

  10. 获取考试成绩的sql语句

    as score,t_answer.id,t_answer.exams_name,t_answers.answer_id,t_answers.questions_id,t_answers.questi ...