HDU 2825 Wireless Password【AC自动机+DP】
给m个单词,由这m个单词组成的一个新单词(两个单词可以重叠包含)长度为n,且新单词中包含的基本单词数目不少于k个。问这样的新单词共有多少个?
m很小,用二进制表示新单词中包含基本单词的情况。
用m个单词建立AC自动机,可以求出所有单词之间相互包含的情况,AC自动机的后缀特性(每个结点的失配边指向新结点,新节点到trie树根的字符串是当前节点字符串的后缀)。
动态规划:
f(i, j, k):长度为i的单词,在trie树中第j个结点处,包含基本单词的情况为k(二进制),的总方案数。
转移方程:
在当前字符串后边再加上一个字母
f(i+1, u, k|val[u]) += f(i, j, k)
u是j结点的子结点(或者是失配边指向的结点),k|val[u]表示加上一个新字母后包含基本单词的情况。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
struct AC_Automata {
#define N 102
#define M 26
int ch[N][M], val[N], last[N], f[N], sz;
void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
int idx(char c) { return c-'a'; } void insert(char s[], int v) {
int u = 0;
for (int i=0; s[i]; i++) {
int c = idx(s[i]);
if (!ch[u][c]) {
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = 1<<v;
}
void build() {
queue<int> q;
f[0] = 0;
for (int c=0; c<M; c++) {
int u = ch[0][c];
if (u) { f[u] = last[u] = 0; q.push(u); }
}
while (!q.empty()) {
int r = q.front(); q.pop();
for (int c=0; c<M; c++) {
int u = ch[r][c];
if (!u) {
ch[r][c] = ch[f[r]][c];
val[r] = val[r] | val[f[r]]; //从根到当前结点组成的字符串后缀包含基本单词的情况(传递)
continue;
}
q.push(u);
f[u] = ch[f[r]][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
}
} ac;
int c[1030]; ///记录每个状态含有几个串
int f[27][102][1025]; void init() {
memset(c, 0, sizeof(c));
for (int i=0; i<1024; i++) {
for (int j=0; j<10; j++)
if ((1<<j) & i) c[i]++;
}
}
void solve(int n, int m, int p) {
#define Mod 20090717
int u;
for (int i=0; i<=n; i++)
for (int j=0; j<ac.sz; j++)
for (int k=0; k<(1<<m); k++)
f[i][j][k] = 0;
f[0][0][0] = 1; for (int i=0; i<n; i++)
for (int j=0; j<ac.sz; j++) {
for (int k=0; k<(1<<m); k++) {
if (f[i][j][k] == 0) continue;
for (int jj=0; jj<M; jj++) {
u = ac.ch[j][jj];
f[i+1][u][ac.val[u]|k] = (f[i+1][u][ac.val[u]|k] + f[i][j][k]) % Mod;
}
}
} int ans = 0;
for (int i=0; i<ac.sz; i++)
for (int j=0; j<(1<<m); j++)
if (c[j] >= p) ans = (ans + f[n][i][j]) % Mod;
printf("%d\n", ans);
}
int main() {
int n, m, k;
char s[12];
init(); while (scanf("%d%d%d", &n, &m, &k) == 3) {
if (n == 0 && m == 0 && k == 0) break;
ac.clear(); for (int i=0; i<m; i++) {
scanf(" %s", s);
ac.insert(s, i);
}
ac.build(); solve(n, m, k); }
return 0;
}
HDU 2825 Wireless Password【AC自动机+DP】的更多相关文章
- HDU 2825 Wireless Password(AC自动机+DP)
题目链接 做题, #include <cstdio> #include <string> #include <cstring> using namespace st ...
- HDU 2825 Wireless Password (AC自己主动机,DP)
pid=2825">http://acm.hdu.edu.cn/showproblem.php? pid=2825 Wireless Password Time Limit: 2000 ...
- hdu 2825 Wireless Password(ac自己主动机&dp)
Wireless Password Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- HDU - 2825 Wireless Password(AC自己主动机+DP)
Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...
- hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...
- 【HDU2825】Wireless Password (AC自动机+状压DP)
Wireless Password Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u De ...
- HDU2825 Wireless Password —— AC自动机 + 状压DP
题目链接:https://vjudge.net/problem/HDU-2825 Wireless Password Time Limit: 2000/1000 MS (Java/Others) ...
- HDU - 2825 Wireless Password (AC自动机+状压DP)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2825 题意:给一些字符串,构造出长度为n的字符串,它至少包含k个所给字符串,求能构造出的个数. 题解: ...
- HDU 2825 Wireless Password(AC自动机 + 状压DP)题解
题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个 思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上. 代码: #include<cmath> ...
随机推荐
- Qt Quick快速入门之信号、槽
信号和槽主要用于组件之间的通信,类似于.net和java中的委托. 使用QObject::connect方法将信号与槽关联起来,然后信号的发起者发出信号,接受者中的槽函数就会执行. 比如connect ...
- 【二分】【预处理】zoj4029 Now Loading!!!
题意:给定一个序列,多次询问 将a数组从小到大排序,下面那个值只有不超过32种,于是预处理f[i][j],表示分母为i时,aj/i的前缀和是多少. 然后对于一个给定的p,一定将分母划分成了一些连续的段 ...
- 算法转AI平台工程师记录-0
--- vim源码安装: 1. git clone https://github.com/vim/vim.git 2. cd vim && ./configure --prefix=x ...
- bzoj 3252: 攻略 -- 长链剖分+贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MB Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神 ...
- Codeforces Round #352 (Div. 1) A. Recycling Bottles 暴力
A. Recycling Bottles 题目连接: http://www.codeforces.com/contest/671/problem/A Description It was recycl ...
- [置顶] iOS中让省略号垂直居中
在显示等待框时,一般要求在提示信息后面加个省略号,但中文输入法下输入的省略号是在底部对齐,但中 文的习惯是省略号垂直居中对齐,最后找到下面这个方法来显示垂直居中的省略号: 中文和英文输入法下一样: o ...
- Clever Little Box 电缆组件 USB A 插座 至 USB B 插头
http://china.rs-online.com/web/p/usb-cable-assemblies/7244156/ 产品详细信息 USB3.0适配器 superspeed USB将提供10x ...
- MVC扩展控制器, 把部分视图转换成字符串(带验证信息), 并以json传递给前端视图
当我们使用jQuery异步提交表单数据的时候,需要把部分视图转换成字符串(带验证信息),以json的形式传递给前端视图. 使用jQuery异步加载部分视图,返回内容追加到页面某个div: jQ ...
- [转载] C-MEX程序编写
原作者,胡荣春 2006-10-11 1 MEX文件简介 在MATLAB中可调用的C或Fortran语言程序称为MEX文件.MATLAB可以直接把MEX文件视为它的内建函数进行调用.MEX文件是动态 ...
- msgpack配合FIREDAC传输多表数据
msgpack配合FIREDAC传输多表数据 procedure TForm1.Button1Click(Sender: TObject);var ms, ms2: TMemoryStream; pa ...