DNA Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 15422 | Accepted: 5954 |
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
题目链接:
http://poj.org/problem?id=2778
题目大意:
有m种DNA序列式有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列。
解题思路:
首先根据给出的序列构造ac自动机,自动机的每个节点是一种状态,在序列末尾添加一个字符就是一次状态转移。这样这道题就是要在每个序列末尾的节点做上标记,然后求在自动机上进行n次状态转移且不经过任何标记的方法数。
我们将自动机看作一个有向图,问题转化为求从节点a到节点b经过n个节点的方法数。我们得到该有向图的邻接矩阵,求邻接矩阵的n次幂mat,mat[a][b]即为答案。
AC代码:
import java.util.*;
public class Main {
static int n,ct;
static long m,mod=100000,ans;
static int[] mp=new int[305];
static int[] mm=new int[105];
static int[] ff=new int[105];
static int[][] ch=new int[105][4];
static long[][] bb=new long[105][105];
static long[][] xx=new long[105][105];
static long[][] res=new long[105][105];
static Queue<Integer> q=new LinkedList<Integer>();
static void clear(int u)
{
ch[u][0]=ch[u][1]=ch[u][2]=ch[u][3]=0;
}
static void insert(char[] s)
{
int u=0,a;
for(int i=0;i<s.length;i++)
{
a=mp[s[i]];
if(ch[u][a]==0)
{
ch[u][a]=++ct;
clear(ct);
}
u=ch[u][a];
}
mm[u]=1;
}
static void build()
{
q.clear();int u,v,r;
for(int i=0;i<4;i++)
{
u=ch[0][i];
if(u>0) { q.add(u);ff[u]=0;}
}
while(!q.isEmpty())
{
r=q.poll();v=ff[r];
if(mm[v]==1) mm[r]=1;
for(int i=0;i<4;i++)
{
u=ch[r][i];
if(u==0) ch[r][i]=ch[v][i];
else { ff[u]=ch[v][i];q.add(u);}
}
}
}
static void get_mat()
{
for(int i=0;i<=ct;i++)
{
for(int j=0;j<=ct;j++)
xx[i][j]=0;
for(int j=0;j<4;j++)
if(mm[ch[i][j]]==0) xx[i][ch[i][j]]++;
}
}
static void mul_mat(long[][] xx,long[][] yy)
{
for(int i=0;i<=ct;i++)
for(int j=0;j<=ct;j++)
{
bb[i][j]=0;
for(int k=0;k<=ct;k++)
bb[i][j]=(bb[i][j]+xx[i][k]*yy[k][j]%mod)%mod;
}
for(int i=0;i<=ct;i++)
for(int j=0;j<=ct;j++)
xx[i][j]=bb[i][j];
}
static void pow_mat(long n)
{
for(int i=0;i<=ct;i++)
{
for(int j=0;j<=ct;j++)
res[i][j]=0;
res[i][i]=1;
}
while(n>0)
{
if((n&1)>0) mul_mat(res,xx);
mul_mat(xx,xx);n>>=1;
}
}
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
mp['A']=0;mp['T']=1;
mp['C']=2;mp['G']=3;
while(in.hasNext())
{
n=in.nextInt();m=in.nextLong();
clear(0);ct=0;
Arrays.fill(mm,0);
for(int i=1;i<=n;i++)
insert(in.next().toCharArray());
build();
get_mat();pow_mat(m);
ans=0;
for(int i=0;i<=ct;i++)
ans=(ans+res[0][i])%mod;
System.out.println(ans);
}
}
}