hdu2825

题意

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

分析

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

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

code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<queue>
  5. using namespace std;
  6. typedef long long ll;
  7. const int MAXN = 1e2 + 10;
  8. const int MOD = 20090717;
  9. struct Trie {
  10. int root, L, nxt[MAXN][26], fail[MAXN], val[MAXN];
  11. int newnode() {
  12. memset(nxt[L], -1, sizeof nxt[L]);
  13. return L++;
  14. }
  15. void init() {
  16. L = 0;
  17. root = newnode();
  18. memset(val, 0, sizeof val);
  19. memset(fail, 0, sizeof fail);
  20. }
  21. void insert(int id, char S[]) {
  22. int len = strlen(S);
  23. int now = root;
  24. for(int i = 0; i < len; i++) {
  25. int d = S[i] - 'a';
  26. if(nxt[now][d] == -1) nxt[now][d] = newnode();
  27. now = nxt[now][d];
  28. }
  29. val[now] |= (1 << id);
  30. }
  31. void build() {
  32. queue<int> Q;
  33. for(int i = 0; i < 26; i++) {
  34. if(nxt[root][i] == -1) nxt[root][i] = 0;
  35. else { fail[nxt[root][i]] = root; Q.push(nxt[root][i]); }
  36. }
  37. while(!Q.empty()) {
  38. int now = Q.front(); Q.pop();
  39. val[now] |= val[fail[now]];
  40. for(int i = 0; i < 26; i++) {
  41. if(nxt[now][i] == -1) nxt[now][i] = nxt[fail[now]][i];
  42. else { fail[nxt[now][i]] = nxt[fail[now]][i]; Q.push(nxt[now][i]); }
  43. }
  44. }
  45. }
  46. }trie;
  47. int dp[30][MAXN][1024];
  48. int cnt[1024];
  49. int main() {
  50. int n, m, k;
  51. cnt[0] = 0;
  52. for(int i = 1; i < 1024; i++) {
  53. int j = 0;
  54. while(!((i >> j) & 1)) j++;
  55. cnt[i] = cnt[i - (1 << j)] + 1;
  56. }
  57. while(~scanf("%d%d%d", &n, &m, &k) && (n + m + k)) {
  58. trie.init();
  59. for(int i = 0; i < m; i++) {
  60. char s[15];
  61. scanf("%s", s);
  62. trie.insert(i, s);
  63. }
  64. trie.build();
  65. for(int i = 0; i <= n; i++) {
  66. for(int j = 0; j < trie.L; j++) {
  67. for(int k = 0; k < (1 << m); k++) {
  68. dp[i][j][k] = 0;
  69. }
  70. }
  71. }
  72. dp[0][0][0] = 1;
  73. for(int i = 0; i < n; i++) {
  74. for(int j = 0; j < trie.L; j++) {
  75. for(int bit = 0; bit < (1 << m); bit++) {
  76. if(!dp[i][j][bit]) continue;
  77. for(int k = 0; k < 26; k++) {
  78. int tmp = trie.nxt[j][k];
  79. (dp[i + 1][tmp][trie.val[tmp] | bit] += dp[i][j][bit]) %= MOD;
  80. }
  81. }
  82. }
  83. }
  84. int sum = 0;
  85. for(int i = 0; i < trie.L; i++) {
  86. for(int j = 0; j < (1 << m); j++) {
  87. if(cnt[j] >= k) sum = (sum + dp[n][i][j]) % MOD;
  88. }
  89. }
  90. printf("%d\n", sum);
  91. }
  92. return 0;
  93. }

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. IE提示是否只查看安全传送的网页内容

    IE选项-->安全-->点上面那个地球internet-->点下面那个 自定义级别-->找到“其他”-->显示混合内容,改为启用,重启打开下IE,就可以了

  2. 洛谷 P2801 教主的魔法 解题报告

    P2801 教主的魔法 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.--.N. ...

  3. 一个acm过来人的心得

    刻苦的训练我打算最后稍微提一下.主要说后者:什么是有效地训练? 我想说下我的理解.        很多ACMer入门的时候,都被告知:要多做题,做个500多道就变牛了.其实,这既不是充分条件.也不会是 ...

  4. Android 对Layout_weight属性完全解析以及使用ListView来实现表格

    用在linearlayout 如果我们想要按照权重比例来分配LinearLayout,我们需要将其宽度设置为0dip http://blog.csdn.net/xiaanming/article/de ...

  5. Html 让文字显示在图片的上面

    如题: 第一种方式便是将 image 作为背景图片,即:background-image:url("......."); 在此可以控制背景图片的横向和纵向的平铺: backgrou ...

  6. (转)C/S 与 B/S 区别

    感谢:http://www.cnblogs.com/xiaoshuai/archive/2010/05/25/1743741.html C/S结构,即Client/Server(客户机/服务器)结构, ...

  7. 「6月雅礼集训 2017 Day2」A

    [题目大意] 给出一棵树,求有多少对点(u,v)满足其路径上不存在两个点a,b满足(a,b)=1 n<=10^5 [题解] 考虑找出所有不符合的点对,共有n*ln(n)对,他们要么是祖先-> ...

  8. bzoj 2668 费用流

    我们可以把初始状态转化为目标状态这一约束转化为将黑子移动到目标状态所需要的最少步数. 除了初始点和目标点之外,剩下的点如果被经过那么就会被交换两次,所以我们将一个点拆成3个点,a,b,c,新建附加源点 ...

  9. python configparse

    # 参考:https://www.cnblogs.com/lily1989/p/8401005.html # https://blog.csdn.net/willhuo/article/details ...

  10. js三层引号嵌套

    ··· 参考:https://blog.csdn.net/feiyangbaxia/article/details/49681131 第一层用双引号,第二层转义双引号,第三层单引号