您的位置:首页 > 产品设计 > UI/UE

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:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: