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
题目大意
给出m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列。(仅含A,T,C,G四个字符)
题解
首先以所有疾病序列为模板串构建Trie树和AC自动机的fail指针。将序列末尾节点设置为危险点,而fail指针指向的点是危险点的点也设置为危险点。在建好的Trie树中删去所有的危险点。不难想到在这棵Trie树上从0节点开始走n步有多少种走法,答案即为多少。
考虑建造一个矩阵mat,mat[i][j] 表示从i节点1步走到j节点有多少种方案。那么
matn
即为答案。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<memory>
#include<vector>
#include<deque>
#include<cmath>
#include<ctime>
#include<queue>
#include<list>
#include<map>
#include<set>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define F(i,j,n) for(register int i=j;i<=n;i++)
#define D(i,j,n) for(register int i=j;i>=n;i--)
#define ll long long
#define db double
using namespace std;
inline void in(int &x);
inline void in(ll &x);
const int mod = 100000, max_size = 100 + 10, ch_size = 4;
int m, n;
char s[20];
struct Matrix{
int p, q;
ll mat[max_size][max_size];
Matrix(){memset(mat, 0, sizeof(mat));}
}m1;
Matrix operator *(Matrix m1, Matrix m2){
Matrix m3;
m3.p = m1.p; m3.q = m2.q;
for(int i = 0; i < m3.p; i++)
for(int j = 0; j < m3.q; j++){
int ret = 0;
for(int k = 0; k < m1.q; k++)
ret += (m1.mat[i][k] * m2.mat[k][j]) % mod;
m3.mat[i][j] = ret % mod;
}
return m3;
}
Matrix matrix_pow(Matrix x, int y){
Matrix res;
res.p = x.p, res.q = x.q;
for(int i = 0; i < res.p; i++)
for(int j = 0; j < res.q; j++)
res.mat[i][j] = m1.mat[i][j];
while(y){
if (y & 1) res = res * x;
x = x * x;
y >>= 1;
}
return res;
}
struct Trie{
int ch[max_size][ch_size];
int val[max_size], f[max_size];
int sz;
int idx[200];
Trie(){sz = 1; idx['A'] = 0; idx['G'] = 1; idx['C'] = 2; idx['T'] = 3;}
void insert(char *s){
int u = 0, len = strlen(s);
for(int i = 0; i < len; i++){
int x = idx[s[i]];
if(!ch[u][x]){
ch[u][x] = sz++;
val[sz] = 0;
}
u = ch[u][x];
}
val[u] = 1;
}
void get_fail(){
queue<int> q;
f[0] = 0;
for(int i = 0; i < ch_size; i++){
int u = ch[0][i];
if(u){
f[u] = 0;
q.push(u);
}
}
while(!q.empty()){
int r = q.front(); q.pop();
if(val[f[r]]) val[r] = 1;
for(int i = 0; i < ch_size; i++){
int &u = ch[r][i];
if(!u){
u = ch[f[r]][i];
continue;
}
q.push(u);
f[u] = ch[f[r]][i];
}
}
}
void build(){
m1.p = m1.q = sz;
for(int i = 0; i < sz; i++)
for(int j = 0; j < ch_size; j++)
if(!val[i] && !val[ch[i][j]])
m1.mat[i][ch[i][j]]++;
}
}ac;
void init(){
scanf("%d%d", &m, &n);
for(int i = 1; i <= m; i++){
scanf("%s", s);
ac.insert(s);
}
}
void work(){
ac.get_fail();
ac.build();
m1 = matrix_pow(m1, n-1);
int ans = 0;
for(int i = 0; i < m1.p; i++)
ans += m1.mat[0][i];
printf("%d\n", ans % mod);
}
int main(){
freopen("poj2778.in", "r", stdin);
freopen("poj2778.out", "w", stdout);
init();
work();
return 0;
}
inline void in(int &x){
x = 0; int f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){x = x*10 + ch - '0'; ch = getchar();}
x *= f;
}
inline void in(ll &x){
x = 0; ll f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){x = x*10 + ch - '0'; ch = getchar();}
x *= f;
}