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\n", ans);

143     }

144     return 0;

145 }

 

你可能感兴趣的:(sequence)