和前几天做的AC自动机类似。

  思路简单但是代码200余行。。

  假设solve_sub(i)表示长度为i的不含危险单词的总数。

  最终答案为用总数(26^1+26^2+...+26^n)减去(solve_sub(1)+solve_sub(2)+...+solve_sub(n))。前者构造f[i]=f[i-1]*26+26然后矩阵快速幂即可(当然也可以分治的方法)。后者即构造出dp矩阵p,然后计算(p^1+p^2+...+p^n),对其分治即可。

  代码如下:

  1. #include <stdio.h>
  2. #include <algorithm>
  3. #include <string.h>
  4. #include <vector>
  5. #include <queue>
  6. #include <iostream>
  7. using namespace std;
  8. const int MAX_Tot = + ;
  9. const int mod = ;
  10. typedef unsigned long long ull;
  11.  
  12. int m,n;
  13.  
  14. struct matrix
  15. {
  16. ull e[MAX_Tot][MAX_Tot];
  17. int n,m;
  18. matrix() {}
  19. matrix(int _n,int _m): n(_n),m(_m) {memset(e,,sizeof(e));}
  20. matrix operator * (const matrix &temp)const
  21. {
  22. matrix ret = matrix(n,temp.m);
  23. for(int i=;i<=ret.n;i++)
  24. {
  25. for(int j=;j<=ret.m;j++)
  26. {
  27. for(int k=;k<=m;k++)
  28. {
  29. ret.e[i][j] += e[i][k]*temp.e[k][j];
  30. }
  31. }
  32. }
  33. return ret;
  34. }
  35. matrix operator + (const matrix &temp)const
  36. {
  37. matrix ret = matrix(n,m);
  38. for(int i=;i<=n;i++)
  39. {
  40. for(int j=;j<=m;j++)
  41. {
  42. ret.e[i][j] += e[i][j]+temp.e[i][j];
  43. }
  44. }
  45. return ret;
  46. }
  47. void getE()
  48. {
  49. for(int i=;i<=n;i++)
  50. {
  51. for(int j=;j<=m;j++)
  52. {
  53. e[i][j] = i==j?:;
  54. }
  55. }
  56. }
  57. };
  58.  
  59. matrix qpow(matrix temp,int x)
  60. {
  61. int sz = temp.n;
  62. matrix base = matrix(sz,sz);
  63. base.getE();
  64. while(x)
  65. {
  66. if(x & ) base = base * temp;
  67. x >>= ;
  68. temp = temp * temp;
  69. }
  70. return base;
  71. }
  72.  
  73. matrix solve(matrix a, int k)
  74. {
  75. if(k == ) return a;
  76. int n = a.n;
  77. matrix temp = matrix(n,n);
  78. temp.getE();
  79. if(k & )
  80. {
  81. matrix ex = qpow(a,k);
  82. k--;
  83. temp = temp + qpow(a,k/);
  84. return temp * solve(a,k/) + ex;
  85. }
  86. else
  87. {
  88. temp = temp + qpow(a,k/);
  89. return temp * solve(a,k/);
  90. }
  91. }
  92.  
  93. struct Aho
  94. {
  95. struct state
  96. {
  97. int nxt[];
  98. int fail,cnt;
  99. }stateTable[MAX_Tot];
  100.  
  101. int size;
  102.  
  103. queue<int> que;
  104.  
  105. void init()
  106. {
  107. while(que.size()) que.pop();
  108. for(int i=;i<MAX_Tot;i++)
  109. {
  110. memset(stateTable[i].nxt,,sizeof(stateTable[i].nxt));
  111. stateTable[i].fail = stateTable[i].cnt = ;
  112. }
  113. size = ;
  114. }
  115.  
  116. void insert(char *s)
  117. {
  118. int n = strlen(s);
  119. int now = ;
  120. for(int i=;i<n;i++)
  121. {
  122. char c = s[i];
  123. if(!stateTable[now].nxt[c-'a'])
  124. stateTable[now].nxt[c-'a'] = size++;
  125. now = stateTable[now].nxt[c-'a'];
  126. }
  127. stateTable[now].cnt = ;
  128. }
  129.  
  130. void build()
  131. {
  132. stateTable[].fail = -;
  133. que.push();
  134.  
  135. while(que.size())
  136. {
  137. int u = que.front();que.pop();
  138. for(int i=;i<;i++)
  139. {
  140. if(stateTable[u].nxt[i])
  141. {
  142. if(u == ) stateTable[stateTable[u].nxt[i]].fail = ;
  143. else
  144. {
  145. int v = stateTable[u].fail;
  146. while(v != -)
  147. {
  148. if(stateTable[v].nxt[i])
  149. {
  150. stateTable[stateTable[u].nxt[i]].fail = stateTable[v].nxt[i];
  151. // 在匹配fail指针的时候顺便更新cnt
  152. if(stateTable[stateTable[stateTable[u].nxt[i]].fail].cnt == )
  153. stateTable[stateTable[u].nxt[i]].cnt = ;
  154. break;
  155. }
  156. v = stateTable[v].fail;
  157. }
  158. if(v == -) stateTable[stateTable[u].nxt[i]].fail = ;
  159. }
  160. que.push(stateTable[u].nxt[i]);
  161. }
  162. /*****建立自动机nxt指针*****/
  163. else
  164. {
  165. if(u == ) stateTable[u].nxt[i] = ;
  166. else
  167. {
  168. int p = stateTable[u].fail;
  169. while(p != - && stateTable[p].nxt[i] == ) p = stateTable[p].fail;
  170. if(p == -) stateTable[u].nxt[i] = ;
  171. else stateTable[u].nxt[i] = stateTable[p].nxt[i];
  172. }
  173. }
  174. /*****建立自动机nxt指针*****/
  175. }
  176. }
  177. }
  178.  
  179. matrix build_matrix()
  180. {
  181. matrix ans = matrix(size,size);
  182. for(int i=;i<size;i++)
  183. {
  184. for(int j=;j<;j++)
  185. {
  186. if(!stateTable[i].cnt && !stateTable[stateTable[i].nxt[j]].cnt)
  187. ans.e[i+][stateTable[i].nxt[j]+]++;
  188. }
  189. }
  190. return ans;
  191. }
  192. }aho;
  193.  
  194. void print(matrix p)
  195. {
  196. int n = p.n;
  197. int m = p.m;
  198. for(int i=;i<=n;i++)
  199. {
  200. for(int j=;j<=m;j++)
  201. {
  202. printf("%d ",p.e[i][j]);
  203. }
  204. puts("");
  205. }
  206. }
  207.  
  208. int main()
  209. {
  210. while(scanf("%d%d",&m,&n) == )
  211. {
  212. aho.init();
  213. char s[];
  214. for(int i=;i<=m;i++)
  215. {
  216. scanf("%s",s);
  217. aho.insert(s);
  218. }
  219. aho.build();
  220. matrix p = aho.build_matrix();
  221. p = solve(p,n);
  222. ull temp = ;
  223. for(int i=;i<=aho.size;i++) temp += p.e[][i];
  224. matrix t = matrix(,);
  225. t.e[][] = ;
  226. matrix A = matrix(,);
  227. A.e[][] = A.e[][] = ; A.e[][] = ;
  228. t = t * qpow(A,n);
  229. ull ans = t.e[][] - temp;
  230. printf("%llu\n",ans);
  231. }
  232. return ;
  233. }

  最后觉得,,我之前矩阵模板里的print()真好用啊233= =。

HDU 2243 考研路茫茫――单词情结 ——(AC自动机+矩阵快速幂)的更多相关文章

  1. hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <23 ...

  2. HDU 2243 考研路茫茫——单词情结(AC自动机+DP+快速幂)

    题目链接 错的上头了... 这题是DNA的加强版,26^1 +26^2... - A^1-A^2... 先去学了矩阵的等比数列求和,学的是第二种方法,扩大矩阵的方法.剩下就是各种模板,各种套. #in ...

  3. hdu 2243 考研路茫茫——单词情结 AC自动机 矩阵幂次求和

    题目链接 题意 给定\(N\)个词根,每个长度不超过\(5\). 问长度不超过\(L(L\lt 2^{31})\),只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个? 思路 状态(AC自动 ...

  4. [hdu2243]考研路茫茫——单词情结(AC自动机+矩阵快速幂)

    题意:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个. 解题关键:利用补集转化的思想,先求一个词根也不包含的单词个数,然后用总的减去即可.长度不超过L需要用矩阵维数增加一倍 ...

  5. hdu 2243 考研路茫茫——单词情结(AC自动+矩阵)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. hdu_2243_考研路茫茫——单词情结(AC自动机+矩阵)

    题目链接:hdu_2243_考研路茫茫——单词情结 题意: 让你求包含这些模式串并且长度不小于L的单词种类 题解: 这题是poj2788的升级版,没做过的强烈建议先做那题. 我们用poj2778的方法 ...

  7. HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  8. HDU 2243 考研路茫茫——单词情结

    考研路茫茫——单词情结 Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID ...

  9. HDU 2243 考研路茫茫——单词情结 求长度小于等于L的通路总数的方法

    http://acm.hdu.edu.cn/showproblem.php?pid=2243 这是一题AC自动机 + 矩阵快速幂的题目, 首先知道总答案应该是26^1 + 26^2 + 26^3 .. ...

  10. HDU2243 考研路茫茫——单词情结 ——AC自动机、矩阵优化

    题目链接:https://vjudge.net/problem/HDU-2243 考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memor ...

随机推荐

  1. Sql Server根据字符串拆分多列

    select parsename(REPLACE(Field,',','.'),3) as segment_1, parsename(REPLACE(Field,',','.'),2) as segm ...

  2. cookie和session,sessionStorage、localStorage和cookie的区别

    1.cookie 含义: 存储在访问者的计算机中的变量,即存储在客户端 创建一个cookie /* getCookie方法判断document.cookie对象中是否存有cookie,若有则判断该co ...

  3. stm32位带

    #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bit ...

  4. EditText编辑框

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  5. DRDA

    在谈到分布式DB2数据时,有必要谈谈DRDA. DRDA代表分布式关系数据库体系结构. 它是由IBM开发的一种体系结构,它使关系数据能够在多个平台之间分布. 平台和平台都可以相互通信. 例如,一个DB ...

  6. redis目录

    一.redis基础 二.django-redis 三.redis数据操作详解 四.redis持久化

  7. 用js刷剑指offer(调整数组顺序使奇数位于偶数前面)

    题目描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 牛客网链接 js代码 ...

  8. Petrozavodsk Winter Training Camp 2018 Jagiellonian U Contest Problem A. XOR

    先把所有的数异或起来 得到sum 然后sum有一些位是1一些位是0 是0的位表示所有数里面有这位的数是偶数个 则无论怎么划分数 这一位对最终的答案都是不会有贡献的  因为偶数=偶数+偶数/奇数+奇数 ...

  9. java之高并发与多线程

    进程和线程的区别和联系 从资源占用,切换效率,通信方式等方面解答 线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元:而把传统的进程称为重型进程(H ...

  10. Nginx中ngx_http_proxy_module模块

    该模块允许将请求传递给另⼀一台服务器器指令:1 ,proxy_pass设置代理理服务器器的协议和地址以及应映射位置的可选 URI .作为协议,可以指定“ http 或 https .可以将地址指定为域 ...