建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. 【翻译自mos文章】改变数据库用户sysman(该用户是DB Control Repository 的schema)password的方法

    改变数据库用户sysman(该用户是DB Control Repository 的schema)password的方法 參考原文: How To Change the Password of the ...

  2. 面试题之——将文件夹下java文件写入到新的文件夹,并修改扩展名

    题目:将d:/code/java文件夹下的所有.java文件复制到d:/code/java/jad文件夹下并且将原来的文件的扩展名.java改为.jad 源代码: package com.zyh.in ...

  3. Java基础笔记-面向对象2

    构造函数:(当类中没有定义构造函数时,系统会默认给该类加入一个空参数的构造函数) 格式: class Person { Person(){} //空参数 } 1.函数名与类名相同, 2,不定义返回值类 ...

  4. html系列教程--input label

    <input> 标签:用于提交用户输入数据的文本框. input属性: 1.checked:用于checkbox,radio等元素,确定是否选中,true/false 2.disabled ...

  5. 【整理】Ajax异步实现的几种方式总结

    AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术.GET ...

  6. 使用EXTEND方式来分段处理大表的搬数据

    创建一个表: 记录rowid的分区段并作为处理的日志表: DROP TABLE DEAL_TABLE_EXTENT; CREATE TABLE DEAL_TABLE_EXTENT(seq        ...

  7. [转]取代cookie的网站追踪技术:”帆布指纹识别”初探

    [前言] 一般情况下,网站或者广告联盟都会非常想要一种技术方式可以在网络上精确定位到每一个个体,这样可以通过收集这些个体的数据,通过分析后更加精准的去推送广告(精准化营销)或其他有针对性的一些活动.C ...

  8. Intellij Idea的一些配置

    1.字体 修改IDEA面板字体:Settings->Appearance-> Override default fonts by(not recommended)选中,选择自己喜欢的字体 ...

  9. Windows下C++多线程同步与互斥简单运用

    1.  互斥量,Mutex #include <Windows.h> #include <iostream> using namespace std; DWORD WINAPI ...

  10. C语言版推箱子

    推箱子源代码初步: #include<stdio.h> #include<conio.h> #include<stdlib.h> #define boolean i ...