DNA Sequence
Description
It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to analyze a segment of DNA Sequence,For example, if a animal's DNA sequence contains segment ATC then it may mean that the animal may have a genetic disease. Until now scientists have found several those segments, the problem is how many kinds of DNA sequences of a species don't contain those segments.
Suppose that DNA sequences of a species is a sequence that consist of A, C, T and G,and the length of sequences is a given integer n. Input
First line contains two integer m (0 <= m <= 10), n (1 <= n <=2000000000). Here, m is the number of genetic disease segment, and n is the length of sequences.
Next m lines each line contain a DNA genetic disease segment, and length of these segments is not larger than 10. Output
An integer, the number of DNA sequences, mod 100000.
Sample Input 4 3 AT AC AG AA Sample Output 36 Source |
题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列。(仅含A,T,C,G四个字符)
首先处理患病的DNA串,连接为字典树后,添加fail指针,完成AC自动机,给每个节点一个编号,然后用矩阵统计每个节点走一步可以走到的节点的种数,其中,不能包含会患病的序列,最后矩阵相乘。
在处理危险串时,注意除了危险串的末节点要舍弃以外,若某节点的last指向末节点时,也要舍弃。
还有在处理矩阵的时候要用long long,否则会出错。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 105;
const int kind = 4;
const int mod = 100000;
struct Matrix
{
int n, m;
ll a[maxn][maxn];
void clear()
{
n = m = 0;
memset(a, 0, sizeof(a));
}
Matrix operator *(const Matrix &b) const
{
Matrix temp;
temp.clear();
temp.n = n;temp.m = b.m;
for (int i = 0;i < n;i++)
{
for (int j = 0;j < b.m;j++)
{
for (int k = 0;k < m;k++)
temp.a[i][j] = (temp.a[i][j]+a[i][k] * b.a[k][j]) % mod;
temp.a[i][j] %= mod;
}
}
return temp;
}
};
Matrix pow(Matrix a, int n)
{
Matrix temp;
temp.n = temp.m = a.n;
for (int i = 0;i < a.n;i++)
{
for (int j = 0;j < a.n;j++)
temp.a[i][j] = i == j ? 1 : 0;
}
while (n)
{
if (n & 1)
temp = temp*a;
a = a*a;
n >>= 1;
}
return temp;
}
Matrix matrix;
struct node
{
int sz, ch[maxn][kind];
int val[maxn], fail[maxn],last[maxn];
void init()
{
sz = 1; val[0] = 0;
memset(ch[0], 0, sizeof(ch[0]));
}
int idx(char c)
{
if (c == 'A') return 0;
if (c == 'T') return 1;
if (c == 'C') return 2;
if (c == 'G') return 3;
}
void insert(char *s,int v)
{
int u = 0, n = strlen(s);
for (int i = 0;i < n;i++)
{
int id = idx(s[i]);
if(!ch[u][id])
{
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
ch[u][id] = sz++;
}
u = ch[u][id];
}
val[u] = v;
}
void getFail()
{
queue<int>q;
fail[0] = 0;
for (int i = 0;i < kind;i++)
{
int u = ch[0][i];
if (u)
{
fail[u] = 0, last[u] = 0;
q.push(u);
}
}
while (!q.empty())
{
int r = q.front();
q.pop();
for (int i = 0;i < kind;i++)
{
int u = ch[r][i];
if (!u)
{
ch[r][i] = ch[fail[r]][i];
continue;
}
q.push(u);
int v = fail[r];
while (v&&!ch[v][i]) v = fail[v];
fail[u] = ch[v][i];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
}
void buildMatrix()
{
matrix.clear();
matrix.n = sz; matrix.m = sz;
for (int i = 0;i < sz;i++)
{
if (val[i] || last[i]) continue;
for (int j = 0;j < kind;j++)
{
int u = i;
while (u&&!ch[u][j]) u = fail[u];
u = ch[u][j];
if(!val[u]&&!val[last[u]])
matrix.a[i][u]++;
}
}
}
};
node ac;
char P[20];
int main()
{
ll m, n;
while (scanf("%lld%lld", &m, &n) != EOF)
{
ac.init();
for (int i = 1;i <= m;i++)
{
scanf("%s", P);
ac.insert(P,i);
}
ac.getFail();
ac.buildMatrix();
Matrix ans;
ans=pow(matrix, n);
ll sum = 0;
for (int i = 0;i < ac.sz;i++)
sum = (ans.a[0][i]+sum)%mod;
sum = sum%mod;
printf("%lld\n", sum);
}
return 0;
}