Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 12726 | Accepted: 4862 |
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.
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.
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
推荐一个网址 :Maxtrix67
/** 题意:给出n个字符串,问长度为m的字符串中有多少没有包含病毒 做法:AC自动机 + 矩阵快速幂 Maxtrix 67 给出的定理8 经典题目8 给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值 把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。 令C=A*A, 那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过2条边的路径数(枚举k为中转点)。 类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数。同理,如果要求经过k步的路径数, 我们只需要二分求出A^k即可。 **/ #include <iostream> #include <cmath> #include <stdio.h> #include <algorithm> #include <string.h> #include <queue> #include <map> #define MM 10 #define mod 100000 using namespace std; struct Matrix { unsigned long long mat[140][140]; int n; Matrix(){} Matrix(int _n) { n = _n; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { mat[i][j] = 0; } } } Matrix operator *(const Matrix &b) const { Matrix res = Matrix(n); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { res.mat[i][j] = 0; for(int k=0;k<n;k++) { res.mat[i][j] += mat[i][k] * b.mat[k][j]; } res.mat[i][j] %= mod; } } return res; } }; unsigned long long quick_pow(unsigned long long a,int n) { unsigned long long res = 1; unsigned long long tmp = a; while(n) { if(n&1) res *= tmp; tmp *= tmp; n >>= 1; } return res; } Matrix quick_pow(Matrix a,int n) { Matrix res = Matrix(a.n); for(int i=0;i<a.n;i++) { res.mat[i][i] = 1; } Matrix tmp = a; while(n) { if(n&1) res =res * tmp; tmp = tmp * tmp; n >>= 1; } return res; } struct Tire { int next[110][MM],fail[110]; bool end[110]; int L,root; map<char,int>id; int newnode() { for(int i=0;i<MM;i++) { next[L][i] = -1; } end[L++] = 0; return L-1; } void init() { L = 0; root = newnode(); id['A'] = 0; id['T'] = 1; id['C'] = 2; id['G'] = 3; } void insert(char buf[]) { int now = root; int len = strlen(buf); for(int i=0;i<len;i++) { if(next[now][id[buf[i]]] == -1) next[now][id[buf[i]]] = newnode(); now = next[now][id[buf[i]]]; } end[now] = true; } void build() { queue<int>que; int now = root; fail[root] = root; for(int i=0;i<4;i++) { if(next[now][i] == -1) next[now][i] = root; else { fail[next[now][i]] = root; que.push(next[now][i]); } } while(!que.empty()) { now = que.front(); que.pop(); if(end[fail[now]]) end[now] = true; for(int i=0;i<4;i++) { if(next[now][i] == -1) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]] = next[fail[now]][i]; que.push(next[now][i]); } } } } Matrix getMatrix() { Matrix res = Matrix(L+1); for(int i=0;i<L;i++) { for(int j=0;j<4;j++) { if(end[next[i][j]] == false && !end[i]) res.mat[i][next[i][j]] ++; } } return res; } }; char buf[100]; Tire ac; int main() { // freopen("in.txt","r",stdin); int n,m; while(~scanf("%d %d",&n,&m)) { ac.init(); for(int i=0;i<n;i++) { scanf("%s",buf); ac.insert(buf); } ac.build(); Matrix a = ac.getMatrix(); a = quick_pow(a,m); unsigned long long res = 0; for(int i=0;i<a.n;i++) { res += a.mat[0][i]; } cout<<res%mod<<endl; } return 0; }