POJ2778

题意:只有四种字符的字符串(A, C, T and G),有M中字符串不能出现,为长度为n的字符串可以有多少种。

题解:在字符串上有L中状态,所以就有L*A(字符个数)中状态转移。这里自动机的build的hdu2222略有不同。

那一题中通过询问时循环来求she的he,但是如果he不能出现,she就算不是禁止的字符串也不可出现,所以在build的时候就记录所有不能出现的状态。

  1. if (end[ fail[now] ]) end[now]++;

然后用一个矩阵F来记录可以相互到达的状态就OK了。

矩阵可以理解为用长度为1的字符串两个状态可以相互达到,而F=F^n,F[i][j]就是字符串长度为n时状态i到状态j的路径。

  1. #include <stdio.h>
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <string.h>
  5. #include <queue>
  6. #include <set>
  7. using namespace std;
  8.  
  9. const int N = ;
  10. const int A = ;
  11. const int M = ;
  12. const int MOD = ;
  13.  
  14. typedef vector<int> vec;
  15. typedef vector<vec> mat;
  16.  
  17. mat mul(mat &A, mat &B)
  18. {
  19. mat C(A.size(), vec(B[].size()));
  20. for (int i = ; i < A.size(); ++i) {
  21. for (int k = ; k < B.size(); ++k) {
  22. for (int j = ; j < B[].size(); ++j) {
  23. C[i][j] = (C[i][j] + (long long)A[i][k] * B[k][j]) % MOD;
  24. }
  25. }
  26. }
  27. return C;
  28. }
  29.  
  30. // A^n
  31. mat pow(mat A, int n)
  32. {
  33. mat B(A.size(), vec(A.size()));
  34. for (int i = ; i < A.size(); ++i)
  35. B[i][i] = ;
  36. while (n > ) {
  37. if (n & ) B = mul(B, A);
  38. A = mul(A, A);
  39. n >>= ;
  40. }
  41. return B;
  42. }
  43.  
  44. struct ACAutomata {
  45.  
  46. int next[N][A], fail[N], end[N];
  47. int root, L;
  48.  
  49. int idx(char ch)
  50. {
  51. switch(ch) {
  52. case 'A': return ;
  53. case 'C': return ;
  54. case 'T': return ;
  55. case 'G': return ;
  56. }
  57. return -;
  58. }
  59. int newNode()
  60. {
  61. for (int i = ; i < A; ++i) next[L][i] = -;
  62. end[L] = ;
  63. return L++;
  64. }
  65. void init()
  66. {
  67. L = ;
  68. root = newNode();
  69. }
  70. void insert(char buf[])
  71. {
  72. int len = strlen(buf);
  73. int now = root;
  74. for (int i = ; i < len; ++i) {
  75. int ch = idx(buf[i]);
  76. if (next[now][ch] == -) next[now][ch] = newNode();
  77. now = next[now][ch];
  78. }
  79. end[now]++;
  80. }
  81. void build()
  82. {
  83. queue<int> Q;
  84. fail[root] = root;
  85. for (int i = ; i < A; ++i) {
  86. if (next[root][i] == -) {
  87. next[root][i] = root;
  88. } else {
  89. fail[ next[root][i] ] = root;
  90. Q.push( next[root][i] );
  91. }
  92. }
  93. while (Q.size()) {
  94. int now = Q.front();
  95. Q.pop();
  96. if (end[ fail[now] ]) end[now]++; //!!
  97. for (int i = ; i < A; ++i) {
  98. if (next[now][i] == -) {
  99. next[now][i] = next[ fail[now] ][i];
  100. } else {
  101. fail[ next[now][i] ] = next[ fail[now] ][i];
  102. Q.push(next[now][i]);
  103. }
  104. }
  105. }
  106. }
  107.  
  108. int query(int n)
  109. {
  110. mat F(L, vec(L));
  111. for (int i = ; i < L; ++i) {
  112. for (int j = ; j < L; ++j) {
  113. F[i][j] = ;
  114. }
  115. }
  116. for (int i = ; i < L; ++i) {
  117. for (int j = ; j < A; ++j) {
  118. int nt = next[i][j];
  119. if (!end[nt]) F[i][nt]++;
  120. }
  121. }
  122. F = pow(F, n);
  123. int res = ;
  124. for (int i = ; i < L; ++i) {
  125. res = (res + F[][i]) % MOD;
  126. }
  127. return res;
  128. }
  129.  
  130. } ac;
  131.  
  132. char buf[];
  133. int main()
  134. {
  135. int m, n;
  136. while (~scanf("%d%d", &m, &n)) {
  137. ac.init();
  138. while (m--) {
  139. scanf("%s", buf);
  140. ac.insert(buf);
  141. }
  142. ac.build();
  143. printf("%d\n", ac.query(n));
  144. }
  145.  
  146. return ;
  147. }

HDU 2243上题要求不存在给定字符串,而这题要求存在至少一个。于是方法就是总方法减去不存在的就是答案了。

题目要求是小于等于L的,所以矩阵加一维记录前缀和就好了。

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. typedef unsigned long long ull;
  6. typedef vector<ull> vec;
  7. typedef vector<vec> mat;
  8. const int N = ;
  9. const int A = ;
  10. const int M = ;
  11.  
  12. mat mul(mat &A, mat &B)
  13. {
  14. mat C(A.size(), vec(B[].size()));
  15. for (int i = ; i < A.size(); ++i) {
  16. for (int k = ; k < B.size(); ++k) {
  17. for (int j = ; j < B[].size(); ++j) {
  18. C[i][j] += A[i][k] * B[k][j];
  19. }
  20. }
  21. }
  22. return C;
  23. }
  24.  
  25. mat pow(mat A, ull n)
  26. {
  27. mat B(A.size(), vec(A.size()));
  28. for (int i = ; i < A.size(); ++i)
  29. B[i][i] = ;
  30. while (n > ) {
  31. if (n & ) B = mul(B, A);
  32. A = mul(A, A);
  33. n >>= ;
  34. }
  35. return B;
  36. }
  37.  
  38. struct ACAutomata {
  39.  
  40. int next[N][A], fail[N], end[N];
  41. int root, L;
  42.  
  43. int idx(char ch)
  44. {
  45. return ch - 'a';
  46. }
  47. int newNode()
  48. {
  49. for (int i = ; i < A; ++i) next[L][i] = -;
  50. end[L] = ;
  51. return L++;
  52. }
  53. void init()
  54. {
  55. L = ;
  56. root = newNode();
  57. }
  58. void insert(char buf[])
  59. {
  60. int len = strlen(buf);
  61. int now = root;
  62. for (int i = ; i < len; ++i) {
  63. int ch = idx(buf[i]);
  64. if (next[now][ch] == -) next[now][ch] = newNode();
  65. now = next[now][ch];
  66. }
  67. end[now]++;
  68. }
  69. void build()
  70. {
  71. queue<int> Q;
  72. fail[root] = root;
  73. for (int i = ; i < A; ++i) {
  74. if (next[root][i] == -) {
  75. next[root][i] = root;
  76. } else {
  77. fail[ next[root][i] ] = root;
  78. Q.push( next[root][i] );
  79. }
  80. }
  81. while (Q.size()) {
  82. int now = Q.front();
  83. Q.pop();
  84. if (end[ fail[now] ]) end[now]++;
  85. for (int i = ; i < A; ++i) {
  86. if (next[now][i] == -) {
  87. next[now][i] = next[ fail[now] ][i];
  88. } else {
  89. fail[ next[now][i] ] = next[ fail[now] ][i];
  90. Q.push(next[now][i]);
  91. }
  92. }
  93. }
  94. }
  95.  
  96. ull query(ull n)
  97. {
  98. mat F(L+, vec(L+));
  99. for (int i = ; i <= L; ++i) {
  100. for (int j = ; j <= L; ++j) {
  101. F[i][j] = ;
  102. }
  103. }
  104. for (int i = ; i <= L; ++i) F[i][L] = ;
  105. for (int i = ; i < L; ++i) {
  106. for (int j = ; j < A; ++j) {
  107. int nt = next[i][j];
  108. if (!end[nt]) F[i][nt]++;
  109. }
  110. }
  111. F = pow(F, n+);
  112. return F[][L] - ;
  113. }
  114.  
  115. } ac;
  116.  
  117. char aff[];
  118. int main()
  119. {
  120. int n;
  121. ull m;
  122. while (~scanf("%d%llu", &n, &m)) {
  123. ac.init();
  124. while (n--) {
  125. scanf("%s", aff);
  126. ac.insert(aff);
  127. }
  128. ac.build();
  129. ull ans1 = ac.query(m);
  130. mat F(, vec());
  131. mat S(, vec()); S[][] = ; S[][] = ;
  132. F[][] = ; F[][] = ;
  133. F[][] = ; F[][] = ;
  134. F = pow(F, m);
  135. S = mul(F, S);
  136. ull ans2 = S[][];
  137. printf("%llu\n", ans2 - ans1);
  138. }
  139. return ;
  140. }

POJ1625

同poj2778,不过没有取模操作,需要大数。

大数不可以矩阵快速幂吗?内存不够……

使用dp递推,递推公式也比较简单。

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <iostream>
  4. #include <queue>
  5. #include <map>
  6.  
  7. using namespace std;
  8.  
  9. typedef vector<int> vec;
  10. typedef vector<vec> mat;
  11. const int N = ;
  12. const int A = ;
  13.  
  14. map<char, int> mp;
  15.  
  16. struct BigInt
  17. {
  18. const static int mod = ;
  19. const static int DLEN = ;
  20. int a[],len;
  21. BigInt()
  22. {
  23. memset(a,,sizeof(a));
  24. len = ;
  25. }
  26. BigInt(int v)
  27. {
  28. memset(a,,sizeof(a));
  29. len = ;
  30. do
  31. {
  32. a[len++] = v%mod;
  33. v /= mod;
  34. }while(v);
  35. }
  36. BigInt(const char s[])
  37. {
  38. memset(a,,sizeof(a));
  39. int L = strlen(s);
  40. len = L/DLEN;
  41. if(L%DLEN)len++;
  42. int index = ;
  43. for(int i = L-;i >= ;i -= DLEN)
  44. {
  45. int t = ;
  46. int k = i - DLEN + ;
  47. if(k < )k = ;
  48. for(int j = k;j <= i;j++)
  49. t = t* + s[j] - '';
  50. a[index++] = t;
  51. }
  52. }
  53. BigInt operator +(const BigInt &b)const
  54. {
  55. BigInt res;
  56. res.len = max(len,b.len);
  57. for(int i = ;i <= res.len;i++)
  58. res.a[i] = ;
  59. for(int i = ;i < res.len;i++)
  60. {
  61. res.a[i] += ((i < len)?a[i]:)+((i < b.len)?b.a[i]:);
  62. res.a[i+] += res.a[i]/mod;
  63. res.a[i] %= mod;
  64. }
  65. if(res.a[res.len] > )res.len++;
  66. return res;
  67. }
  68. BigInt operator *(const BigInt &b)const
  69. {
  70. BigInt res;
  71. for(int i = ; i < len;i++)
  72. {
  73. int up = ;
  74. for(int j = ;j < b.len;j++)
  75. {
  76. int temp = a[i]*b.a[j] + res.a[i+j] + up;
  77. res.a[i+j] = temp%mod;
  78. up = temp/mod;
  79. }
  80. if(up != )
  81. res.a[i + b.len] = up;
  82. }
  83. res.len = len + b.len;
  84. while(res.a[res.len - ] == &&res.len > )res.len--;
  85. return res;
  86. }
  87. void output()
  88. {
  89. printf("%d",a[len-]);
  90. for(int i = len-;i >= ;i--)
  91. printf("%04d",a[i]);
  92. printf("\n");
  93. }
  94. };
  95.  
  96. struct ACAutomata {
  97.  
  98. int next[N][A], fail[N], end[N];
  99. int root, L;
  100.  
  101. int idx(char ch)
  102. {
  103. return mp[ch];
  104. }
  105. int newNode()
  106. {
  107. for (int i = ; i < A; ++i) next[L][i] = -;
  108. end[L] = ;
  109. return L++;
  110. }
  111. void init()
  112. {
  113. L = ;
  114. root = newNode();
  115. }
  116. void insert(char buf[])
  117. {
  118. int len = strlen(buf);
  119. int now = root;
  120. for (int i = ; i < len; ++i) {
  121. int ch = idx(buf[i]);
  122. if (next[now][ch] == -) next[now][ch] = newNode();
  123. now = next[now][ch];
  124. }
  125. end[now]++;
  126. }
  127. void build()
  128. {
  129. queue<int> Q;
  130. fail[root] = root;
  131. for (int i = ; i < A; ++i) {
  132. if (next[root][i] == -) {
  133. next[root][i] = root;
  134. } else {
  135. fail[ next[root][i] ] = root;
  136. Q.push( next[root][i] );
  137. }
  138. }
  139. while (Q.size()) {
  140. int now = Q.front();
  141. Q.pop();
  142. if (end[ fail[now] ]) end[now]++; //!!
  143. for (int i = ; i < A; ++i) {
  144. if (next[now][i] == -) {
  145. next[now][i] = next[ fail[now] ][i];
  146. } else {
  147. fail[ next[now][i] ] = next[ fail[now] ][i];
  148. Q.push(next[now][i]);
  149. }
  150. }
  151. }
  152. }
  153. mat query(int n)
  154. {
  155. mat F(L, vec(L));
  156. for (int i = ; i < L; ++i) {
  157. for (unsigned j = ; j < mp.size(); ++j) {
  158. int nt = next[i][j];
  159. if (!end[nt]) F[i][nt]++;
  160. }
  161. }
  162. return F;
  163. }
  164.  
  165. } ac;
  166.  
  167. char word[];
  168. BigInt dp[][];
  169. int main()
  170. {
  171. int n, m, p;
  172. while (~scanf("%d%d%d", &n, &m, &p)) {
  173. ac.init();
  174. getchar();
  175. gets(word);
  176. mp.clear();
  177. for (unsigned i = ; i < strlen(word); ++i) mp[ word[i] ] = i;
  178. while (p--) {
  179. gets(word);
  180. ac.insert(word);
  181. }
  182. ac.build();
  183. mat F = ac.query(m);
  184.  
  185. int now = ;
  186. dp[now][] = ;
  187. for (int i = ; i < ac.L; ++i) dp[now][i] = ;
  188. for (int i = ; i <= m; ++i) {
  189. now ^= ;
  190. for (int j = ; j < ac.L; ++j) dp[now][j] = ;
  191. for (int j = ; j < ac.L; ++j)
  192. for (int k = ; k < ac.L; ++k)
  193. if (F[j][k]) dp[now][k] = dp[now][k] + dp[now^][j] * F[j][k];
  194. }
  195. BigInt res = ;
  196. for (int i = ; i < ac.L; ++i) res = res + dp[now][i];
  197. res.output();
  198. }
  199. return ;
  200. }

POJ2778&HDU2243&POJ1625(AC自动机+矩阵/DP)的更多相关文章

  1. hdu2243之AC自动机+矩阵乘法

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

  2. [poj2778]DNA Sequence(AC自动机+矩阵快速幂)

    题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) 解题关键:AC自动机,实际上就是一个状态转移图,注意能少取模就少取模, ...

  3. POJ2778 DNA Sequence(AC自动机 矩阵)

    先使用AC自动机求得状态转移关系,再建立矩阵,mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数,则此矩阵的n次方表示n步从i,到j的方法数. #include<cstdio& ...

  4. BZOJ 1009 GT考试(ac自动机+矩阵DP)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1009 题意:给定一个长度为m的串s.有多少种长度为n的串不包含s? 思路:(1)将s插入 ...

  5. poj2778 DNA Sequence(AC自动机+矩阵快速幂)

    Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's ve ...

  6. 关于AC自动机和DP的联系

    首先是描述个大概.不说一些特殊的DP 或者借用矩阵来状态转移 (这些本质都是一样的). 只讲AC自动机和DP的关系(个人理解). AC自动机 又可以叫做状态机. 我一开始的认为.AC 自动机提供了一些 ...

  7. bzoj 2553: [BeiJing2011]禁忌 AC自动机+矩阵乘法

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2553 题解: 利用AC自动机的dp求出所有的转移 然后将所有的转移储存到矩阵中,进行矩阵 ...

  8. Censored! POJ - 1625 AC自动机+大数DP

    题意: 给出一n种字符的字典,有p个禁用的单词, 问能组成多少个不同的长度为m的合法字符串.(m<=50) 题解: 是不是个我们之前做的题目非常非常像,题意都一样. 直接将上次写的AC自动机+矩 ...

  9. 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 682  Solved: 364 Description 我们称一 ...

随机推荐

  1. C++11新特性:Lambda函数(匿名函数)

    声明:本文参考了Alex Allain的文章http://www.cprogramming.com/c++11/c++11-lambda-closures.html 加入了自己的理解,不是简单的翻译 ...

  2. HDU1180+BFS

    bfs思路:三维标记状态 && 处理好 - | 和时刻的关系即可 /* bfs 思路:三维标记状态 && 处理好 - | 和时刻的关系即可 */ #include< ...

  3. linux为命令取别名

    在linux的命令中,有些命令很长并且经常使用到,我们可以为命令添加一个别名,格式如下: $ alias 别名='命令' 例如: # 列出home文件夹的文件 $ alias lsh='ls -l / ...

  4. Android中如何取消调转界面后EditText默认获取聚焦问题

    最近在做一个项目,当我点击跳转至一个带有EditText的界面后,模拟器中的软键盘会自动弹出,严重影响了用户体验.在网上找了资料,现总结如下. 我们知道,EditText有一个 android:foc ...

  5. SQLite入门与分析(三)---内核概述(1)

    写在前面:从本章开始,我们开始进入SQLite的内核.为了能更好的理解SQLite,我先从总的结构上讨论一下内核,从全局把握SQLite很重要.SQLite的内核实现不是很难,但是也不是很简单.总的来 ...

  6. 安装Ubuntu双系统系列——更换源

    Ubuntu 有一个非常有用的命令 apt-get,它可以帮助你下载软件,还可以安装,下载并安装的命令是 apt-get install. 那Ubuntu默认是从哪里下载软件呢,这可以查看文件/etc ...

  7. Why it is good practice to declare loggers private, static, and final?

    // Jakarta Commons Loggingprivate static final Log log = LogFactory.getLog(MyClass.class);The above ...

  8. linux文件系统-基本磁盘2

    直入主题-基本磁盘 硬盘数据按照不同特点和作用大致分为5部分:MBR区.DBR区.FAT区.DIR区和DATA区 1.MBR MBR(Main Boot Record 主引导记录区)位于整个硬盘的0磁 ...

  9. int21 h

    表:DOS系统功能调INT 21H AH 功能 调用参数 返回参数 00 程序终止(同INT 20H) CS=程序段前缀 01 键盘输入并回显 AL=输入字符 02 显示输出 DL=输出字符 03 异 ...

  10. xp宿主机和VMware下Ubuntu12.04共享文件夹

    VMware下Windows与Linux共享文件的方法有很多,比如Samba等等,我这里介绍简单地通过设置VMware来达到共享的目的. 打开VMware的设置,在"options" ...