程序员人生 网站导航

poj 2778 AC自动机与矩阵连乘

栏目:php教程时间:2015-06-08 08:31:11

http://poj.org/problem?id=2778

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
/** poj 2778 AC自动机与矩阵连乘 题目大意:给定1些模式串,问可以构造出多少中长度为n且不含模式串中的任何1个作为子串的字符串 解题思路:构造自动机,写出状态转移的矩阵,进行矩阵快速幂,其n次幂就表示长度为n。然后mat[0][i]就表示从根节点到状态点i长度为n的字符串有多少种 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #include <queue> using namespace std; const int MOD=100000; struct Matrix { int mat[110][110],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 ret=Matrix(n); for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { for(int k=0; k<n; k++) { int tmp=(long long)mat[i][k]*b.mat[k][j]%MOD; ret.mat[i][j]=(ret.mat[i][j]+tmp)%MOD; } } } return ret; } }; struct Trie { int next[110][4],fail[110],end[110]; int root,L; int newnode() { for(int i=0; i<4; i++) next[L][i]=⑴; end[L++]=0; return L⑴; } void init() { L=0; root=newnode(); } int getch(char ch) { if(ch=='A') return 0; if(ch=='C') return 1; if(ch=='G') return 2; return 3; } void insert(char *s) { int len=strlen(s); int now=root; for(int i=0; i<len; i++) { if(next[now][getch(s[i])]==⑴) next[now][getch(s[i])]=newnode(); now=next[now][getch(s[i])]; } end[now]=1; } void build() { queue <int>Q; for(int i=0; i<4; i++) { if(next[root][i]==⑴) next[root][i]=root; else { fail[next[root][i]]=root; Q.push(next[root][i]); } } while(!Q.empty()) { int now=Q.front(); Q.pop(); if(end[fail[now]]==1) end[now]=1; for(int i=0; i<4; i++) { if(next[now][i]==⑴) next[now][i]=next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } } Matrix getMatrix() { Matrix res=Matrix(L); for(int i=0; i<L; i++) { for(int j=0; j<4; j++) { if(end[next[i][j]]==0) res.mat[i][next[i][j]]++; } } return res; } } ac; char buf[20]; Matrix pow_M(Matrix a,int n) { Matrix ret=Matrix(a.n); for(int i=0; i<ret.n; i++) { ret.mat[i][i]=1; } Matrix tmp=a; while(n) { if(n&1)ret=ret*tmp; tmp=tmp*tmp; n>>=1; } return ret; } int main() { 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=pow_M(a,m); int ans=0; for(int i=0;i<a.n;i++) { ans=(ans+a.mat[0][i])%MOD; } printf("%d ",ans); } return 0; }


------分隔线----------------------------
------分隔线----------------------------

最新技术推荐