题目大意:有个人想破解他邻居的密码,他邻居告诉了一些关于这个密码的信息,并且给他一个单词集合,他用这些信息判断一下最少有多少种密码。
1->, 所有的密码都是有小写字母组成。
2->,密码的长度是 n (1<= n <=25)。
3->,密码至少包含 k 种字符集里面的单词。
 
比如,给集合{"she", "he"},单词长度是3,最少包含两个单词的密码,很明显只能是“she”(题目表述的不清楚)。
 
分析:因为要统计记录到达每个点时候经过多少种不同的单词,所以需要用一种方法来保存这些信息,开一个数组来判重貌似是个很容易想到的办法,不过考虑时间复杂度的问题,建议还是不要这么干,因为字符集合的数量很少,只有10,所以我们可以使用状态压缩来保存这些信息,而且转移状态时候也很方便操作,不过有点需要注意,一定要把遍历子节点放在最内层循环,这样再遍历每一种状态的时候发先有0的情况可以continue一下,否则超时超的哇哇的.......
 
代码如下:
==========================================================================
  1. #include<iostream>
  2. #include<algorithm>
  3. #include<stdio.h>
  4. #include<string.h>
  5. #include<queue>
  6. using namespace std;
  7.  
  8. const int MAXN = ;
  9. const int MaxSon = ;
  10. const int Mod = ;
  11. const int oo = 1e9+;
  12.  
  13. struct Ac_Trie
  14. {
  15. int next[MAXN][MaxSon];
  16. int Fail[MAXN], End[MAXN];
  17. int cnt, root;
  18.  
  19. int newnode()
  20. {
  21. for(int i=; i<MaxSon; i++)
  22. next[cnt][i] = -;
  23. Fail[cnt] = End[cnt] = false;
  24.  
  25. return cnt++;
  26. }
  27. void InIt()
  28. {
  29. cnt = ;
  30. root = newnode();
  31. }
  32.  
  33. void Insert(char s[], int t)
  34. {
  35. int now = root;
  36.  
  37. for(int i=; s[i]; i++)
  38. {
  39. int k = s[i]-'a';
  40.  
  41. if(next[now][k] == -)
  42. next[now][k] = newnode();
  43. now = next[now][k];
  44. }
  45.  
  46. End[now] = <<t;
  47. }
  48. void GetFial()
  49. {
  50. queue<int>Q;
  51. int now = root;
  52.  
  53. for(int i=; i<MaxSon; i++)
  54. {
  55. if(next[now][i] == -)
  56. next[now][i] = root;
  57. else
  58. {
  59. Fail[next[now][i]] = root;
  60. Q.push(next[now][i]);
  61. }
  62. }
  63.  
  64. while(Q.size())
  65. {
  66. now = Q.front();
  67. Q.pop();
  68.  
  69. for(int i=; i<MaxSon; i++)
  70. {
  71. if(next[now][i] == -)
  72. next[now][i] = next[Fail[now]][i];
  73. else
  74. {
  75. Fail[next[now][i]] = next[Fail[now]][i];
  76. Q.push(next[now][i]);
  77. }
  78. }
  79.  
  80. End[now] |= End[Fail[now]];
  81. }
  82. }
  83. };
  84. Ac_Trie ac;
  85.  
  86. int Find(int i)
  87. {
  88. int k=;
  89.  
  90. while(i)
  91. {
  92. if(i % )
  93. k++;
  94. i /= ;
  95. }
  96.  
  97. return k;
  98. }
  99.  
  100. int main()
  101. {
  102. int N, M, K;
  103.  
  104. int sum[] ={};
  105.  
  106. for(int i=; i<; i++)
  107. sum[i] = Find(i);
  108.  
  109. while(scanf("%d%d%d", &N, &M, &K), N+M+K)
  110. {
  111. char s[MAXN];
  112. ac.InIt();
  113.  
  114. for(int i=; i<M; i++)
  115. {
  116. scanf("%s", s);
  117. ac.Insert(s, i);
  118. }
  119.  
  120. ac.GetFial();
  121.  
  122. int dp[][MAXN][] = {}, op=, Len = <<M;
  123. dp[][][] = ;
  124.  
  125. while(N--)
  126. {
  127. memset(dp[op], , sizeof(dp[op]));
  128.  
  129. for(int i=; i<ac.cnt; i++)
  130. for(int k=; k<Len; k++)
  131. {///把k放中间优化一下...否则超时
  132. if(dp[op^][i][k] == )
  133. continue;
  134.  
  135. for(int j=; j<MaxSon; j++)
  136. {
  137. (dp[op][ac.next[i][j]][k|ac.End[i]] += dp[op^][i][k])%=Mod;
  138. }
  139. }
  140.  
  141. op ^= ;
  142. }
  143.  
  144. int ans = ;
  145.  
  146. for(int i=; i<ac.cnt; i++)
  147. for(int j=; j<Len; j++)
  148. {
  149. if(sum[j] >= K || sum[ac.End[i]|j] >= K)
  150. {
  151. ans += dp[op^][i][j];
  152. ans %= Mod;
  153. }
  154. }
  155.  
  156. printf("%d\n", ans);
  157. }
  158.  
  159. return ;
  160. }

Wireless Password - HDU 2825(ac自动机+状态压缩)的更多相关文章

  1. hdu 2825(ac自动机+状态压缩dp)

    题意:容易理解... 分析:在做这道题之前我做了hdu 4057,都是同一种类型的题,因为题中给的模式串的个数最多只能为10个,所以我们就很容易想到用状态压缩来做,但是开始的时候我的代码超时了dp时我 ...

  2. HDU 4511 (AC自动机+状态压缩DP)

    题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4511 题目大意:从1走到N,中间可以选择性经过某些点,比如1->N,或1->2-> ...

  3. hdu 4057(ac自动机+状态压缩dp)

    题意:容易理解... 分析:题目中给的模式串的个数最多为10个,于是想到用状态压缩dp来做,它的状态范围为1-2^9,所以最大为2^10-1,那我们可以用:dp[i][j][k]表示长度为i,在tri ...

  4. hdu 3341(ac自动机+状态压缩)

    题意:容易理解... 思路:首先一开始容易想到要用到dp,开设一个dp[41][41][41][41][501]的数组来解决,但是明显内存已经超出范围了,于是就想如何减少内存呢?只要知道A.T.C.G ...

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

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

  6. HDU 4057 Rescue the Rabbit ( AC自动机 + 状态压缩DP )

    模板来自notonlysuccess. 模式串只有10个,并且重复出现的分值不累加,因此很容易想到状态压缩. 将模式串加入AC自动机,最多有10*100个状态. dp[i][j][k]:串长为i,在T ...

  7. HDU 4758 Walk Through Squares( AC自动机 + 状态压缩DP )

    题意:给你两个串A,B, 问一个串长为M+N且包含A和B且恰好包含M个R的字符串有多少种组合方式,所有字符串中均只含有字符L和R. dp[i][j][k][S]表示串长为i,有j个R,在自动机中的状态 ...

  8. POJ 3691 (AC自动机+状态压缩DP)

    题目链接:  http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...

  9. bzoj1195 神奇的ac自动机+状态压缩dp

    /* 难的不是ac自动机,是状态压缩dp 之前做了一两题类似题目,感觉理解的还不够透彻 */ #include<iostream> #include<cstdio> #incl ...

随机推荐

  1. static 方法.

    If a subclass defines a static method with the same signature as a static method in the superclass, ...

  2. 利用html+ashx实现aspx的功能

    最近准备学习下ASP.NET,初期在网上看了些视频教程,准备将自己学习的东西整理整理,留着日后可以参考参考. 本文采用了html.ashx实现aspx,实现了一个最简单的动态网页效果,开发环境是VS2 ...

  3. Oracle-在线重定义操作文档

    Oracle-在线重定义操作文档 2015年10月8日 15:51 在线重定义的大致操作流程如下: (1)创建基础表A,如果存在,就不需要操作. (2)创建临时的分区表B. (3)开始重定义,将基表A ...

  4. 玩转CSLA.NET小技巧系列二:使用WCF无法上传附件,提示413 Entity Too Large

    背景:由于系统需要展示图片,客户上传图片到本地客户端目录,然后在数据库中存储本地图片地址,和图片二进制数据 错误原因:我是使用CSLA的WCF服务,使用了数据门户,WCF协议使用的是wsHttpBin ...

  5. SGU 172.eXam(二分图染色)

    时间限制:0.25s 空间限制:4M 题意: 将n(n<200)个点分成两个集合,给出m(m<=30000)对不能在一个集合的点对,判断能否分成满足要求的集合,输出其中一个集合和集合的总数 ...

  6. 修改原代码定制bootstrap

    1.下载对应的Bootstarap和node.js 注:less文件夹中包含了bootstrap中所有样式组件的less源代码: dist保存编译后的css和js等文件 2.命令行输入npm inst ...

  7. Invoke()/BeginInvoke()区别

    查看MSDN如下: Control..::.Invoke          ---> 在拥有此控件的基础窗口句柄的线程上执行委托. Control..::.BeginInvoke  ---> ...

  8. asp.net在应用母版的页面下采用了ModalPopupExtender弹出窗中应用autocomplete

    autocomplete是jqueryUI的一个插件,可以实现自动填充的功能. 要点:1.应用了母版页,所以取页面上控件的ID时与一般方法不同 2.由于用了ajax的updatepanel,所以会出现 ...

  9. 如何用DOS 链接mysql

    1.Ctrl+R 打开DOS窗口 2.键入 cd\ 回车进入C盘根目录 3.进入mysql bin目录下 操作mysql命令 4.输入连接数据库命令 mysql -hlocalhost -uroot ...

  10. iOS: 获取文件路径

    iOS: 获取文件路径   // 例如 - (NSString *)applicationDocumentsDirectory { return [NSSearchPathForDirectories ...