给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】的更多相关文章

  1. HDU 2825 Wireless Password(AC自动机+DP)

    题目链接 做题, #include <cstdio> #include <string> #include <cstring> using namespace st ...

  2. HDU 2825 Wireless Password (AC自己主动机,DP)

    pid=2825">http://acm.hdu.edu.cn/showproblem.php? pid=2825 Wireless Password Time Limit: 2000 ...

  3. hdu 2825 Wireless Password(ac自己主动机&amp;dp)

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

  4. HDU - 2825 Wireless Password(AC自己主动机+DP)

    Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...

  5. hdu 4117 GRE Words AC自动机DP

    题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...

  6. 【HDU2825】Wireless Password (AC自动机+状压DP)

    Wireless Password Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u De ...

  7. HDU2825 Wireless Password —— AC自动机 + 状压DP

    题目链接:https://vjudge.net/problem/HDU-2825 Wireless Password Time Limit: 2000/1000 MS (Java/Others)    ...

  8. HDU - 2825 Wireless Password (AC自动机+状压DP)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2825 题意:给一些字符串,构造出长度为n的字符串,它至少包含k个所给字符串,求能构造出的个数. 题解: ...

  9. HDU 2825 Wireless Password(AC自动机 + 状压DP)题解

    题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个 思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上. 代码: #include<cmath> ...

随机推荐

  1. AlertDialog对话框

    普通对话框 public void click1(View v) { //这里不能用 getApplicationContext()方法来获取上下文 AlertDialog.Builder build ...

  2. 【BZOJ 2721】 2721: [Violet 5]樱花 (筛)

    2721: [Violet 5]樱花 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 599  Solved: 354 Description Input ...

  3. SQL SERVER 2008 多边形问题的解决

    报错内容: 在执行用户定义例程或聚合 "geometry" 期间出现 .NET Framework 错误: System.ArgumentException: 24144: 由于该 ...

  4. bzoj 3262

    题意:给你一些三维上的点,对于每个点,统计三个坐标都小于等于该点的点数. 如果点的范围在300以内,可以用三维树状数组搞,但这题坐标范围太大. 考虑将所有点按照x坐标排序,从左到右,相当于在一个二维平 ...

  5. 图解PCB布线数字地、模拟地、电源地,单点接地抗干扰!

    我们在进行pcb布线时总会面临一块板上有两种.三种地的情况,傻瓜式的做法当然是不管三七二十一,只要是地 就整块敷铜了.这种对于低速板或者对干扰不敏感的板子来讲还是没问题的,否则可能导致板子就没法正常工 ...

  6. 正确率、召回率和F值

    正确率.召回率和F值是在鱼龙混杂的环境中,选出目标的重要评价指标. 不妨看看这些指标的定义先: 正确率 = 正确识别的个体总数 /  识别出的个体总数 召回率 = 正确识别的个体总数 /  测试集中存 ...

  7. 从零开始搭建linux下laravel 5.5所需环境(二)

    我们已经装好了nginx,现在我们开始装mysql和php 我们同样使用yum来安装. 先安装MySQL软件(客户端.服务器端.依赖库) yum install -y mysql mysql-serv ...

  8. HP Microserver Gen8 Processor FAQ

    http://homeservershow.com/forums/index.php?/topic/6596-hp-microserver-gen8-processor-faq/ This guide ...

  9. MYSQL 源代码学习

    http://ourmysql.com/ http://blog.chinaunix.net/uid-26896862-id-4009777.html

  10. Access-Control-Allow-Origin,跨域

    1.浏览器的同源安全策略 浏览器只允许请求当前域的资源,而对其他域的资源表示不信任.那怎么才算跨域呢? 请求协议http,https的不同 域domain的不同 端口port的不同 好好好,大概就是这 ...