Language:
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 |
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 110;
const int MOD = 100000;
typedef long long LL;
struct Matrix{
int ary[N][N];
int row, col;
void init() {
memset(ary, 0, sizeof(ary));
}
Matrix (int row = N, int col = N) {
this->row = row, this->col = col;
init();
}
Matrix operator=(const Matrix & A) {
row = A.row;
col = A.col;
for (int i = 0; i < row; ++i)
for (int j = 0; j < col; ++j)
ary[i][j] = A.ary[i][j];
}
};
const Matrix operator*(const Matrix & A, const Matrix & B) {
Matrix t;
t.row = A.row;
t.col = B.col;
for (int i = 0; i < A.row; ++i)
for (int j = 0; j < B.col; ++j) {
for (int k = 0; k < A.col; ++k)
t.ary[i][j] += (int)(((LL)A.ary[i][k] * (LL)B.ary[k][j]) % MOD);
t.ary[i][j] %= MOD;
}
return t;
}
struct Trie{
int next[N][4], fail[N];
bool vis[N];
int total, root;
Matrix mt;
int new_node() {
for (int i = 0; i < 4; ++i)
next[total][i] = -1;
vis[total] = false;
return total++;
}
void init() {
total = 0;
mt.init();
root = new_node();
}
int get_index(char ch) {
if (ch == 'A') return 0;
if (ch == 'T') return 1;
if (ch == 'G') return 2;
return 3;
}
void insert(char *str) {
int cur = root;
while (*str) {
int idx = get_index(*str);
if (next[cur][idx] == -1)
next[cur][idx] = new_node();
cur = next[cur][idx];
++str;
}
vis[cur] = true;
}
void build() {
queue<int> q;
fail[root] = -1;
q.push(root);
while (!q.empty()) {
int cur = q.front();
q.pop();
if (fail[cur] != -1 && vis[fail[cur]] == true)
vis[cur] = true;
for (int i = 0; i < 4; ++i) {
if (next[cur][i] == -1)
next[cur][i] = fail[cur] == -1 ? root : next[fail[cur]][i];
else {
fail[next[cur][i]] = fail[cur] == -1 ? root : next[fail[cur]][i];
q.push(next[cur][i]);
}
}
}
mt.row = mt.col = total;
for (int i = 0; i < total; ++i)
for (int j = 0; j < 4; ++j)
if (vis[next[i][j]] == false)
++mt.ary[i][next[i][j]];
}
}tree;
int quick_pow(Matrix & mt, int n) {
Matrix ans, tmp = mt;
ans.row = mt.row, ans.col = mt.col;
for (int i = 0; i < mt.row; ++i)
ans.ary[i][i] = 1;
while (n) {
if (n & 1)
ans = ans * tmp;
n >>= 1;
tmp = tmp * tmp;
}
int res = 0;
for (int i = 0; i < mt.row; ++i)
res += ans.ary[0][i];
return res % MOD;
}
int main() {
int n, m;
while (~scanf("%d%d", &n, &m)) {
tree.init();
char str[20];
for (int i = 0; i < n; ++i) {
scanf("%s", str);
tree.insert(str);
}
tree.build();
int ans = quick_pow(tree.mt, m);
printf("%d\n", ans);
}
return 0;
}