POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)
2015-06-24 21:54
585 查看
题目链接: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:
题意:有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:
#include <cstdio> #include <cstring> #include <queue> #include <map> using namespace std; const int KIND = 4; const int MAXN = 110; const int MOD = 100000; typedef long long LL; struct Trie { int next[MAXN][KIND], fail[MAXN]; bool isExit[MAXN]; int root, L; map<char, int> mp; LL mat[MAXN][MAXN]; LL ret[MAXN][MAXN]; LL tmp[MAXN][MAXN]; int create() { for (int i = 0; i < KIND; ++i) next[L][i] = -1; isExit[L++] = false; return L - 1; } void init() { L = 0; root = create(); mp['A'] = 0; mp['C'] = 1; mp['G'] = 2; mp['T'] = 3; memset(mat, 0, sizeof(mat)); memset(ret, 0, sizeof(ret)); } void insert(char str[]) { int now = root; int len = strlen(str); for (int i = 0; i < len; ++i) { if (-1 == next[now][mp[str[i]]]) next[now][mp[str[i]]] = create(); now = next[now][mp[str[i]]]; } isExit[now] = true; } void build() { queue<int>Q; for (int i = 0; i < KIND; ++i) { if (-1 == next[root][i]) next[root][i] = root; else { fail[next[root][i]] = root; Q.push(next[root][i]); } } while (!Q.empty()) { int now = Q.front(); Q.pop(); if (isExit[fail[now]]) isExit[now] = true; for (int i = 0; i < KIND; ++i) { if (-1 == next[now][i]) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]] = next[fail[now]][i]; Q.push(next[now][i]); } } } } void getMatrix() { for (int i = 0; i < L; ++i) { for (int j = 0; j < KIND; ++j) { if (!isExit[next[i][j]]) ++mat[i][next[i][j]]; } } } void matrixMul(LL mat1[MAXN][MAXN], LL mat2[MAXN][MAXN]) { LL mat3[MAXN][MAXN]; for (int i = 0; i < L; ++i) { for (int j = 0; j < L; ++j) { mat3[i][j] = 0; for (int k = 0; k < L; ++k) mat3[i][j] = (mat3[i][j] + mat1[i][k] * mat2[k][j]) % MOD; } } memcpy(mat1, mat3, sizeof(mat3)); } void matrixQuickMod(LL n) { getMatrix(); for (int i = 0; i < L; ++i) { ret[i][i] = 1; for (int j = 0; j < L; ++j) tmp[i][j] = mat[i][j]; } while (n) { if (n & 1) matrixMul(ret, tmp); matrixMul(tmp, tmp); n >>= 1; } } }; Trie ac; char str[15]; int main() { int m; LL n; while (scanf("%d %lld", &m, &n) != EOF) { ac.init(); for (int i = 0; i < m; ++i) { scanf("%s", str); ac.insert(str); } ac.build(); ac.matrixQuickMod(n); int ans = 0; for (int i = 0; i < ac.L; ++i) ans = (ans + ac.ret[0][i]) % MOD; printf("%d\n", ans); } return 0; }
相关文章推荐
- 格式化jd-gui反编译源码的行号
- [leetcode] Unique Paths II
- ios UIView的常用属性
- UITextFiled使用总结
- Kaggle-ValueError: Input contains NaN, infinity or a value too large for dtype('float32').
- 关于 UITextField
- ios UIButton的常用属性
- deque时间复杂度和vector,list比较
- IOS UILabel的常用属性
- Android属性之build.prop生成过程
- [leetcode] Unique Paths
- iOS学习笔记(3)UIButton
- UITextField隐藏键盘的几种方式
- Sicily 1443. Printer Queue
- 解决 Errors running builder 'DeploymentBuilder' on project ' .
- View requires API level 14 (current min is 8): <Switch>
- CSU 1658 IQ of XUEXX’s descendants 矩阵快速幂
- C# WebRequest WebClient Post请求Demo
- ZJU2136 Longest Ordered Subsequence
- iOS下载文件之NSData -UIImage