zoukankan      html  css  js  c++  java
  • POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)

    题目链接:http://poj.org/problem?id=2778

    题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列。(仅含A,T,C,G四个字符)

    思路:Trie图的状态转移,用矩阵mat[i][j]来表示从结点i到j只走一步有几种走法,那么mat的n次幂就表示从结点i到j走n步有几种走法,题目要求解的就是从头节点走n步且不包含危险结点的走法。

    mat = mat^n   ans = (mat[0][0] + mat[0][1] + ... + mat[0][num]) num为结点个数

    code:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 #include <map>
      5 using namespace std;
      6 const int KIND = 4;
      7 const int MAXN = 110;
      8 const int MOD = 100000;
      9 typedef long long LL;
     10 
     11 struct Trie
     12 {
     13     int next[MAXN][KIND], fail[MAXN];
     14     bool isExit[MAXN];
     15     int root, L;
     16     map<char, int> mp;
     17     LL mat[MAXN][MAXN];
     18     LL ret[MAXN][MAXN];
     19     LL tmp[MAXN][MAXN];
     20     int create()
     21     {
     22         for (int i = 0; i < KIND; ++i)
     23             next[L][i] = -1;
     24         isExit[L++] = false;
     25         return L - 1;
     26     }
     27     void init()
     28     {
     29         L = 0;
     30         root = create();
     31         mp['A'] = 0;
     32         mp['C'] = 1;
     33         mp['G'] = 2;
     34         mp['T'] = 3;
     35         memset(mat, 0, sizeof(mat));
     36         memset(ret, 0, sizeof(ret));
     37     }
     38     void insert(char str[])
     39     {
     40         int now = root;
     41         int len = strlen(str);
     42         for (int i = 0; i < len; ++i)
     43         {
     44             if (-1 == next[now][mp[str[i]]])
     45                 next[now][mp[str[i]]] = create();
     46             now = next[now][mp[str[i]]];
     47         }
     48         isExit[now] = true;
     49     }
     50     void build()
     51     {
     52         queue<int>Q;
     53         for (int i = 0; i < KIND; ++i)
     54         {
     55             if (-1 == next[root][i])
     56                 next[root][i] = root;
     57             else
     58             {
     59                 fail[next[root][i]] = root;
     60                 Q.push(next[root][i]);
     61             }
     62         }
     63         while (!Q.empty())
     64         {
     65             int now = Q.front();
     66             Q.pop();
     67             if (isExit[fail[now]])
     68                 isExit[now] = true;
     69             for (int i = 0; i < KIND; ++i)
     70             {
     71                 if (-1 == 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     }
     81     void getMatrix()
     82     {
     83         for (int i = 0; i < L; ++i)
     84         {
     85             for (int j = 0; j < KIND; ++j)
     86             {
     87                 if (!isExit[next[i][j]])
     88                     ++mat[i][next[i][j]];
     89             }
     90         }
     91     }
     92     void matrixMul(LL mat1[MAXN][MAXN], LL mat2[MAXN][MAXN])
     93     {
     94         LL mat3[MAXN][MAXN];
     95         for (int i = 0; i < L; ++i)
     96         {
     97             for (int j = 0; j < L; ++j)
     98             {
     99                 mat3[i][j] = 0;
    100                 for (int k = 0; k < L; ++k)
    101                     mat3[i][j] = (mat3[i][j] + mat1[i][k] * mat2[k][j]) % MOD;
    102             }
    103         }
    104         memcpy(mat1, mat3, sizeof(mat3));
    105     }
    106     void matrixQuickMod(LL n)
    107     {
    108         getMatrix();
    109         for (int i = 0; i < L; ++i)
    110         {
    111             ret[i][i] = 1;
    112             for (int j = 0; j < L; ++j)
    113                 tmp[i][j] = mat[i][j];
    114         }
    115         while (n)
    116         {
    117             if (n & 1) matrixMul(ret, tmp);
    118             matrixMul(tmp, tmp);
    119             n >>= 1;
    120         }
    121     }
    122 };
    123 Trie ac;
    124 char str[15];
    125 int main()
    126 {
    127     int m;
    128     LL n;
    129     while (scanf("%d %lld", &m, &n) != EOF)
    130     {
    131         ac.init();
    132         for (int i = 0; i < m; ++i)
    133         {
    134             scanf("%s", str);
    135             ac.insert(str);
    136         }
    137         ac.build();
    138         ac.matrixQuickMod(n);
    139         int ans = 0;
    140         for (int i = 0; i < ac.L; ++i)
    141             ans = (ans + ac.ret[0][i]) % MOD;
    142         printf("%d
    ", ans);
    143     }
    144     return 0;
    145 }
  • 相关阅读:
    android中ping命令的实现
    回溯法——求解0-1背包问题
    scanner使用中遇见的问题
    Eddy&#39;s digital Roots
    项目经理注意事项(3)---宏观把控
    Spring IOC容器
    C++对象模型——Template中的名称决议方式 (第七章)
    比赛对手名单
    猴子吃桃问题
    设计模式-单例模式(02)
  • 原文地址:https://www.cnblogs.com/ykzou/p/4598741.html
Copyright © 2011-2022 走看看