hdu2825

题意

给出一些字符串,要求构造一个长度为 \(n\) 的字符串至少包括其中的 \(k\) 个,问有多少种字符串满足条件。

分析

AC自动机 构造状态转移,然后 状态压缩DP 即可。

\(dp[i][j][k]\) 表示长度为 \(i\) 在 AC自动机上的状态为 \(j\) 已包含的字符串为 \(k\) 时的字符串数量( \(k\) 二进制表示是否有某个给出的字符串)。

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int MAXN = 1e2 + 10;
const int MOD = 20090717;
struct Trie {
int root, L, nxt[MAXN][26], fail[MAXN], val[MAXN];
int newnode() {
memset(nxt[L], -1, sizeof nxt[L]);
return L++;
}
void init() {
L = 0;
root = newnode();
memset(val, 0, sizeof val);
memset(fail, 0, sizeof fail);
}
void insert(int id, char S[]) {
int len = strlen(S);
int now = root;
for(int i = 0; i < len; i++) {
int d = S[i] - 'a';
if(nxt[now][d] == -1) nxt[now][d] = newnode();
now = nxt[now][d];
}
val[now] |= (1 << id);
}
void build() {
queue<int> Q;
for(int i = 0; i < 26; i++) {
if(nxt[root][i] == -1) nxt[root][i] = 0;
else { fail[nxt[root][i]] = root; Q.push(nxt[root][i]); }
}
while(!Q.empty()) {
int now = Q.front(); Q.pop();
val[now] |= val[fail[now]];
for(int i = 0; i < 26; i++) {
if(nxt[now][i] == -1) nxt[now][i] = nxt[fail[now]][i];
else { fail[nxt[now][i]] = nxt[fail[now]][i]; Q.push(nxt[now][i]); }
}
}
}
}trie;
int dp[30][MAXN][1024];
int cnt[1024];
int main() {
int n, m, k;
cnt[0] = 0;
for(int i = 1; i < 1024; i++) {
int j = 0;
while(!((i >> j) & 1)) j++;
cnt[i] = cnt[i - (1 << j)] + 1;
}
while(~scanf("%d%d%d", &n, &m, &k) && (n + m + k)) {
trie.init();
for(int i = 0; i < m; i++) {
char s[15];
scanf("%s", s);
trie.insert(i, s);
}
trie.build();
for(int i = 0; i <= n; i++) {
for(int j = 0; j < trie.L; j++) {
for(int k = 0; k < (1 << m); k++) {
dp[i][j][k] = 0;
}
}
}
dp[0][0][0] = 1;
for(int i = 0; i < n; i++) {
for(int j = 0; j < trie.L; j++) {
for(int bit = 0; bit < (1 << m); bit++) {
if(!dp[i][j][bit]) continue;
for(int k = 0; k < 26; k++) {
int tmp = trie.nxt[j][k];
(dp[i + 1][tmp][trie.val[tmp] | bit] += dp[i][j][bit]) %= MOD;
}
}
}
}
int sum = 0;
for(int i = 0; i < trie.L; i++) {
for(int j = 0; j < (1 << m); j++) {
if(cnt[j] >= k) sum = (sum + dp[n][i][j]) % MOD;
}
}
printf("%d\n", sum);
}
return 0;
}

hdu2825(AC 自动机)的更多相关文章

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

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

  2. 【AC自动机】【状压dp】hdu2825 Wireless Password

    f(i,j,S)表示当前字符串总长度为i,dp到AC自动机第j个结点,单词集合为S时的方案数. 要注意有点卡常数,注意代码里的注释. #include<cstdio> #include&l ...

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

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

  4. 【HDU2825】Wireless Password【AC自动机,状态压缩DP】

    题意 题目给出m(m<=10)个单词,每个单词的长度不超过10且仅由小写字母组成,给出一个正整数n(n<=25)和正整数k,问有多少方法可以组成长度为n的文本且最少包含k个给出的单词. 分 ...

  5. 【hdu2825】ac自动机 + 状压dp

    传送门 题目大意: 给你一些密码片段字符串,让你求长度为n,且至少包含k个不同密码片段串的字符串的数量. 题解: 因为密码串不多,可以考虑状态压缩 设dp[i][j][sta]表示长为i的字符串匹配到 ...

  6. AC自动机基础知识讲解

    AC自动机 转载自:小白 还可参考:飘过的小牛 1.KMP算法: a. 传统字符串的匹配和KMP: 对于字符串S = ”abcabcabdabba”,T = ”abcabd”,如果用T去匹配S下划线部 ...

  7. AC自动机总结

    AC自动机的模板 void buildAC() { while(!q.empty()) q.pop(); q.push(); while(!q.empty()) { int x=q.front();q ...

  8. 【AC自动机&&Trie图】积累

    以前KMP和后缀系列(主要是后缀数组,后缀自动机),都刷了一定数量的题,但是对于AC自动机,却有些冷落,罪过. 但是我感觉,在蓝桥杯比赛中AC自动机出现的概率比后缀系列大,简单的会考匹配,稍难一点会考 ...

  9. 对AC自动机+DP题的一些汇总与一丝总结 (1)

    (1)题意 : 输入n.m.k意思就是给你 m 个模式串,问你构建长度为 n 至少包含 k 个模式串的方案有多少种 分析:(HDU2825) DP[i][j][k] 表示 DP[第几步][哪个节点结尾 ...

随机推荐

  1. 周记【距gdoi:117天】

    国庆被“吞”了 图论还剩下平面图.分层图.欧拉图…… 是现实太残酷还是自己兴趣不够? 努力吧.

  2. ARC076 F Exhausted? Hall定理 + 线段树扫描线

    ---题面--- 题目大意: 有n个人,m个座位,每个人可以匹配的座位是[1, li] || [ri, m],可能有人不需要匹配座位(默认满足),问最少有多少人不能被满足. 题解: 首先可以看出这是一 ...

  3. Notice : brew install php70

    To enable PHP in Apache add the following to httpd.conf and restart Apache: LoadModule php7_module  ...

  4. 关于final局部变量引用的研究

    嵌套类(内部类)方法安全引用外部方法局部变量的原理 嵌套类方法引用外部局部变量,必需将声明为final,否则将出现 Cannot refer to a non-final variable * ins ...

  5. Codeforces 931.D Peculiar apple-tree

    D. Peculiar apple-tree time limit per test 1 second memory limit per test 256 megabytes input standa ...

  6. 如何用listview显示服务端数据

    https://www.cnblogs.com/caobotao/p/5061627.html

  7. 关于ora-12154:TNS:could not resolve the connect identifier specified

    一:前言 刚刚出来实习,在公司配的电脑里面装的oracle和PL SQL时一次性就搞定,但是在自己的电脑上装了就出现这个问题,刚刚在网上看了下,所以自己就写份记载吧! 二: 在打开PLSQL Deve ...

  8. 区间(bzoj 4653)

    Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x ...

  9. Exceptioninthread"main"java.lang.ClassNotFoundsException的问题

    报错如下: Exceptioninthread"main"java.lang.ClassNotFoundsException 大致可以判断出是无法定位到main方法,应该是用mav ...

  10. 【uva11855-求长度为1到n的相同子串出现的次数】sam

    题意:求长度为1到n的相同子串出现的次数,输到小于2为止. 题解: 用sam做. 建机,算right集合,然后用r[i]更新长度为step[i]的子串出现次数,然后ans[i]=maxx(ans[i] ...