POJ 2778 DNA Sequence (AC 自动机+矩阵)

来源:互联网 发布:淘宝发货清单软件 编辑:程序博客网 时间:2024/05/21 21:41
DNA Sequence
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 15064 Accepted: 5806

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 3ATACAGAA

Sample Output

36

Source

POJ Monthly--2006.03.26,dodo

题意:有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;}


0 0