题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个

思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上。

代码:

  1. #include<cmath>
  2. #include<set>
  3. #include<map>
  4. #include<queue>
  5. #include<cstdio>
  6. #include<vector>
  7. #include<cstring>
  8. #include <iostream>
  9. #include<algorithm>
  10. using namespace std;
  11. typedef long long ll;
  12. typedef unsigned long long ull;
  13. const int maxn = 100 + 5;
  14. const int M = 50 + 5;
  15. const ull seed = 131;
  16. const double INF = 1e20;
  17. const int MOD = 20090717;
  18. int n, m, K;
  19. int dp[28][maxn][1100];
  20. int num[1100];
  21. struct Aho{
  22. struct state{
  23. int next[26];
  24. int fail, cnt;
  25. }node[maxn];
  26. int size;
  27. queue<int> q;
  28.  
  29. void init(){
  30. size = 0;
  31. newtrie();
  32. while(!q.empty()) q.pop();
  33. }
  34.  
  35. int newtrie(){
  36. memset(node[size].next, 0, sizeof(node[size].next));
  37. node[size].cnt = node[size].fail = 0;
  38. return size++;
  39. }
  40.  
  41. void insert(char *s, int id){
  42. int len = strlen(s);
  43. int now = 0;
  44. for(int i = 0; i < len; i++){
  45. int c = s[i] - 'a';
  46. if(node[now].next[c] == 0){
  47. node[now].next[c] = newtrie();
  48. }
  49. now = node[now].next[c];
  50. }
  51. node[now].cnt = 1 << id;
  52. }
  53.  
  54. void build(){
  55. node[0].fail = -1;
  56. q.push(0);
  57.  
  58. while(!q.empty()){
  59. int u = q.front();
  60. q.pop();
  61. if(node[node[u].fail].cnt && u) node[u].cnt |= node[node[u].fail].cnt;
  62. for(int i = 0; i < 26; i++){
  63. if(!node[u].next[i]){
  64. if(u == 0)
  65. node[u].next[i] = 0;
  66. else
  67. node[u].next[i] = node[node[u].fail].next[i];
  68. }
  69. else{
  70. if(u == 0) node[node[u].next[i]].fail = 0;
  71. else{
  72. int v = node[u].fail;
  73. while(v != -1){
  74. if(node[v].next[i]){
  75. node[node[u].next[i]].fail = node[v].next[i];
  76. break;
  77. }
  78. v = node[v].fail;
  79. }
  80. if(v == -1) node[node[u].next[i]].fail = 0;
  81. }
  82. q.push(node[u].next[i]);
  83. }
  84. }
  85. }
  86. }
  87.  
  88. void query(){
  89. for(int i = 0; i <= n; i++){
  90. for(int j = 0; j < size; j++){
  91. for(int k = 0; k < (1 << m); k++){
  92. dp[i][j][k] = 0;
  93. }
  94. }
  95. }
  96. for(int i = 0; i < 26; i++){
  97. if(node[node[0].next[i]].cnt){
  98. int v = node[node[0].next[i]].cnt;
  99. dp[1][node[0].next[i]][v]++;
  100. // printf("* %d %d %d\n", 1, node[0].next[i], v);
  101. }
  102. else
  103. dp[1][node[0].next[i]][0]++;
  104. }
  105. for(int i = 1; i < n; i++){
  106. for(int j = 0; j < size; j++){
  107. for(int k = 0; k < (1 << m); k++){
  108. if(dp[i][j][k] == 0) continue;
  109. for(int l = 0; l < 26; l++){
  110. if(node[node[j].next[l]].cnt){
  111. int v = node[node[j].next[l]].cnt;
  112. dp[i + 1][node[j].next[l]][k | v] = (dp[i + 1][node[j].next[l]][k | v] + dp[i][j][k]) % MOD;
  113. }
  114. else{
  115. dp[i + 1][node[j].next[l]][k] = (dp[i + 1][node[j].next[l]][k] + dp[i][j][k]) % MOD;
  116. }
  117. }
  118. }
  119. }
  120. }
  121. int ans = 0;
  122. for(int i = 0; i < size; i++){
  123. for(int j = 0; j < (1 << m); j++){
  124. if(num[j] >= K) ans = (ans + dp[n][i][j]) % MOD;
  125. }
  126. }
  127. printf("%d\n", ans);
  128. }
  129.  
  130. }ac;
  131. char s[100];
  132. int main(){
  133. for(int i = 0; i < 1100; i++){
  134. int temp = 0, x = i;
  135. while(x){
  136. temp += x & 1;
  137. x >>= 1;
  138. }
  139. num[i] = temp;
  140. }
  141. while(~scanf("%d%d%d", &n, &m, &K) && n + m + K){
  142. ac.init();
  143. for(int i = 0; i < m; i++){
  144. scanf("%s", s);
  145. ac.insert(s, i);
  146. }
  147. ac.build();
  148. ac.query();
  149. }
  150. return 0;
  151. }

HDU 2825 Wireless Password(AC自动机 + 状压DP)题解的更多相关文章

  1. hdu2825 Wireless Password(AC自动机+状压dp)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission ...

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

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

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

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

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

    题目大意:给一系列字符串,用小写字母构造出长度为n的至少包含k个字符串的字符串,求能构造出的个数. 题目分析:在AC自动机上走n步,至少经过k个单词节点,求有多少种走法. 代码如下: # includ ...

  5. hdu 4057--Rescue the Rabbit(AC自动机+状压DP)

    题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...

  6. hdu_2825_Wireless Password(AC自动机+状压DP)

    题目链接:hdu_2825_Wireless Password 题意: 给你m个串,问长度为n至少含k个串的字符串有多少个 题解: 设dp[i][j][k]表示考虑到长度为i,第j个自动机的节点,含有 ...

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

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

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

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

  9. hdu 2825 aC自动机+状压dp

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

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

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

随机推荐

  1. Redis 实战 —— 04. Redis 数据结构常用命令简介

    字符串 P39 Redis 的字符串是一个有字节组成的序列,可以存储以下 3 种类型的值:字节串(byte string).整数.浮点数. 在需要的时候, Redis 会将整数转换成浮点数.整数的取值 ...

  2. Redis 实战 —— 05. Redis 其他命令简介

    发布与订阅 P52 Redis 实现了发布与订阅(publish/subscribe)模式,又称 pub/sub 模式(与设计模式中的观察者模式类似).订阅者负责订阅频道,发送者负责向频道发送二进制字 ...

  3. click的简单使用

    click的简单使用 先通过一个简单的例子来认知一下click把 import click @click.command() @click.option('-p', '--port', default ...

  4. 配接Cisco设备

  5. MySQL进阶:约束,多表设计,多表查询,视图,数据库备份与还原

    MySQL进阶 知识点梳理 一.约束 1. 外键约束 为什么要有外键约束 例如:一个user表,一个orderlist 如果现在想要直接删除id为1的张三,但是orderlist里还有用户id为1的订 ...

  6. 向HDFS中指定的文件追加内容,由用户指定内容追加到原有文件的开头或结尾。

    1 import java.io.FileInputStream; 2 import java.io.IOException; 3 import java.text.SimpleDateFormat; ...

  7. SICP 解题集 — SICP 解题集 https://sicp.readthedocs.io/en/latest/

    SICP 解题集 - SICP 解题集 https://sicp.readthedocs.io/en/latest/

  8. 使用Redis有序集合实现投票排行榜系统

    https://mp.weixin.qq.com/s/GcPF8jte8Nzi4Ae0jojXuQ 先说最简单的排行榜.其实之前我们有个用于投票的系统,但是他没有用有序集合,他是这样做的:用redis ...

  9. 判断2个list中是否有相同的数据(相交)Collections.disjoint

    https://blog.csdn.net/yang_niuxxx/article/details/85092490 private void initData() { for (int i = 0; ...

  10. 算法总结篇---AC自动机

    目录 写在前面 算法流程 引例: 概述: Trie树的构建(第一步) 失配指针(第二步) 构建失配指针 字典树和字典图 多模式匹配 例题 写在前面 鸣谢: OiWiki 「笔记」AC 自动机---Lu ...