poj2778

题意

构造只包含 \(A, T, C, G\) 的字符串,且满足不出现指定的一些字符串,问长度为 \(n\) 的字符串有多少种 ?

分析

AC 自动机 + 矩阵快速幂的神题 ,知识点很多。。。

AC 自动机为了给不同的状态之间建边,矩阵快速幂是为了加速状态转移。

比如说一共有 \(5\) 个状态,我要从 状态 \(0\) 转移到 状态 \(4\) ,从 \(0\) 出发,可以先转移到 \(0\) 再转移到 \(4\) ,也可以先转移到 \(1\) 再转移到 \(4\) ,后面类似。

建一个邻接矩阵,\(mat[i][j]\) 表示 \(i\) 转移到 \(j\) 的方案数,想象一下矩阵相乘的情况,\(mat[0][4]\) 的计算过程,神奇。。。

code

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<queue>
  5. using namespace std;
  6. typedef long long ll;
  7. const int MAXN = 105;
  8. const int MOD = 1e5;
  9. int n, m;
  10. struct Matrix {
  11. ll mat[MAXN][MAXN];
  12. void init() {
  13. memset(mat, 0, sizeof mat);
  14. }
  15. };
  16. Matrix operator*(Matrix A, Matrix B) {
  17. Matrix C;
  18. C.init();
  19. for(int i = 0; i < n; i++) {
  20. for(int j = 0; j < n; j++) {
  21. for(int k = 0; k < n; k++) {
  22. C.mat[i][j] = (C.mat[i][j] + A.mat[i][k] * B.mat[k][j]) % MOD;
  23. }
  24. }
  25. }
  26. return C;
  27. }
  28. Matrix operator^(Matrix A, int x) {
  29. Matrix B;
  30. B.init();
  31. for(int i = 0; i < n; i++) B.mat[i][i] = 1;
  32. while(x) {
  33. if(x & 1) B = B * A;
  34. A = A * A;
  35. x >>= 1;
  36. }
  37. return B;
  38. }
  39. struct Trie {
  40. int id[100];
  41. int root, L, nxt[MAXN][4], val[MAXN], fail[MAXN];
  42. int newnode() {
  43. for(int i = 0; i < 4; i++) {
  44. nxt[L][i] = -1;
  45. }
  46. return L++;
  47. }
  48. void init() {
  49. id['A'] = 0; id['T'] = 1; id['C'] = 2; id['G'] = 3;
  50. L = 0;
  51. root = newnode();
  52. memset(val, 0, sizeof val);
  53. }
  54. void insert(char s[15]) {
  55. int len = strlen(s);
  56. int now = root;
  57. for(int i = 0; i < len; i++) {
  58. int d = id[s[i]];
  59. if(nxt[now][d] == -1) nxt[now][d] = newnode();
  60. now = nxt[now][d];
  61. }
  62. val[now] = 1;
  63. }
  64. void build() {
  65. queue<int> Q;
  66. for(int i = 0; i < 4; i++) {
  67. if(nxt[root][i] == -1) nxt[root][i] = root;
  68. else {
  69. fail[nxt[root][i]] = root;
  70. Q.push(nxt[root][i]);
  71. }
  72. }
  73. while(!Q.empty()) {
  74. int now = Q.front(); Q.pop();
  75. if(val[fail[now]]) val[now] = 1;
  76. for(int i = 0; i < 4; i++) {
  77. if(nxt[now][i] == -1) nxt[now][i] = nxt[fail[now]][i];
  78. else {
  79. fail[nxt[now][i]] = nxt[fail[now]][i];
  80. Q.push(nxt[now][i]);
  81. }
  82. }
  83. }
  84. }
  85. Matrix buildMatrix() {
  86. Matrix A; A.init();
  87. for(int i = 0; i < L; i++) {
  88. for(int j = 0; j < 4; j++) {
  89. if(!val[i] && !val[nxt[i][j]]) {
  90. A.mat[i][nxt[i][j]]++;
  91. }
  92. }
  93. }
  94. return A;
  95. }
  96. }trie;
  97. int main() {
  98. trie.init();
  99. int k;
  100. scanf("%d%d", &m, &k);
  101. for(int i = 0; i < m; i++) {
  102. char s[15];
  103. scanf("%s", s);
  104. trie.insert(s);
  105. }
  106. trie.build();
  107. Matrix A = trie.buildMatrix();
  108. n = trie.L;
  109. A = A ^ k;
  110. int ans = 0;
  111. for(int i = 0; i < n; i++) {
  112. ans = (ans + A.mat[0][i]) % MOD;
  113. }
  114. printf("%d\n", ans);
  115. return 0;
  116. }

poj2778(AC 自动机)的更多相关文章

  1. poj2778 ac自动机+矩阵快速幂

    给m个子串,求长度为n的不包含子串的母串数,最直接的应该是暴搜,肯定tle,考虑用ac自动机 将子串建成字典树,通过next表来构造矩阵,然后用矩阵快速幂求长度为n的数量 邻接矩阵https://we ...

  2. poj2778 AC自动机

    以下内容均为转载,,只有代码是自己写的=-= http://blog.csdn.net/morgan_xww/article/details/7834801   转载地址 博主写的很好 ------- ...

  3. 【POJ2778】DNA Sequence(AC自动机,DP)

    题意: 生物课上我们学到,DNA序列中只有A, C, T和G四种片段. 经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段"ATC"是不好片段,则"AGATC ...

  4. 【POJ2778】AC自动机+矩阵乘法

    DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14758 Accepted: 5716 Descrip ...

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

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

  6. POJ2778 DNA Sequence(AC自动机+矩阵快速幂)

    题目给m个病毒串,问不包含病毒串的长度n的DNA片段有几个. 感觉这题好神,看了好久的题解. 所有病毒串构造一个AC自动机,这个AC自动机可以看作一张有向图,图上的每个顶点就是Trie树上的结点,每个 ...

  7. poj2778(AC自动机+矩阵快速幂)

    题意:给你n个字符串,问你长度为m的字符串且字符串中不含有那n个子串的字符串的数量 解题思路:这道题一开始就不太懂,还以为是组合数学的题目,后面看了别人的博客,才知道这是属于AC自动机的另一种用法,是 ...

  8. 【POJ2778】DNA Sequence 【AC自动机,dp,矩阵快速幂】

    题意 题目给出m(m<=10)个仅仅由A,T,C,G组成的单词(单词长度不超过10),然后给出一个整数n(n<=2000000000),问你用这四个字母组成一个长度为n的长文本,有多少种组 ...

  9. poj2778 DNA Sequence【AC自动机】【矩阵快速幂】

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19991   Accepted: 7603 Des ...

随机推荐

  1. [洛谷P2626]斐波那契数列(升级版)

    题目大意:请你求出第$n$个斐波那契数列的数$mod 2^{31}$之后的值.并把它分解质因数. 题解:乱搞 卡点:1.忘记取模 C++ Code: #include<cstdio> #i ...

  2. [Leetcode] Convert sorted list to binary search tree 将排好的链表转成二叉搜索树

    ---恢复内容开始--- Given a singly linked list where elements are sorted in ascending order, convert it to ...

  3. 洛谷 P4168 [Violet]蒲公英 解题报告

    P4168 [Violet]蒲公英 题目背景 亲爱的哥哥: 你在那个城市里面过得好吗? 我在家里面最近很开心呢.昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多 ...

  4. AOJ.502 不只是水仙花

    不只是水仙花 Time Limit: 1000 ms Case Time Limit: 1000 ms Memory Limit: 64 MB Total Submission: 1196 Submi ...

  5. sshd_conf配置

    #    $OpenBSD: sshd_config,v 1.80 2008/07/02 02:24:18 djm Exp $   # This is the sshd server system-w ...

  6. [hdu 4417]树状数组+离散化+离线处理

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 把数字离散化,一个查询拆成两个查询,每次查询一个前缀的和.主要问题是这个数组是静态的,如果带修改 ...

  7. poj 2378 Tree Cutting 树形dp

    After Farmer John realized that Bessie had installed a "tree-shaped" network among his N ( ...

  8. elementUi 组件--el-table

    [需求]在element中,将表格中的数据进行处理,然后渲染出来.例如,将数据保留小数点后两位显示. [知识点]formatter:用来格式化内容 [分析]在element 的table中,实现的过程 ...

  9. oracle查看字符集和修改字符集

    oracle查看字符集和修改字符集 : 查看数据库服务器的字符集: select userenv('language') from dual ; 登陆用dba: 停掉数据库 : shutdown im ...

  10. 【spoj8222-Substrings】sam求子串出现次数

    http://acm.hust.edu.cn/vjudge/problem/28005 题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.求F(1)..F(Length( ...