poj2778

DNA Sequence
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 10031 Accepted: 3762

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

#include <cstdio>
#include <cstring>

const int NODE = 105;
const int CH = 4;
const int mod = 100000;

int chd[NODE][CH], sz = 1;
int word[NODE];
int fail[NODE];
int que[NODE];
int sw[128];

//AC自动机部分
void Ins( char* a )
{
 int p = 0;
 while( *a )
 {
  int c = sw[*a];
  if( !chd[p][c] )
  {
   memset( chd[sz], 0, sizeof(chd[sz]) );
   word[sz] = 0;
   chd[p][c] = sz++;
  }

  p = chd[p][c];
  a++;
 }

 word[p] = 1;
}

void AC( )
{
 int *s = que, *e = que;
 for( int i = 0; i < CH; ++i ) if( chd[0][i] )
 {
  fail[chd[0][i]] = 0;
  *e++ = chd[0][i];
 }

 while( s != e )
 {
  int p = *s++;
  for( int i = 0; i < CH; ++i )
  {
   if( chd[p][i] )
   {
    int v = chd[p][i];
    *e++ = v;
    fail[v] = chd[fail[p]][i];
    word[chd[p][i]] |= word[chd[fail[p]][i]];
   }
   else
    chd[p][i] = chd[fail[p]][i];
  }
 }
}

//矩阵部分
class matrix
{
public:
 __int64 num[NODE][NODE];
 int r, l;

 matrix( int rr = 0, int ll = 0 )
 {
  r = rr;
  l = ll;
  memset(num, 0, sizeof(num));
 }

 matrix operator*( matrix& a )
 {
  int i, j, k;
  matrix result( r, a.l );

  for( i = 0; i < r; ++i )
   for( j = 0; j < a.l; ++j )
   {
    result.num[i][j] = 0;
    //注意这里,如果一边加一边取余的话会很慢···
    //POJ上用C++提交,一边加一边取余,刚好1000MS压过,换这样就200MS+
    for( k = 0; k < l; ++k )
     result.num[i][j] += num[i][k]*a.num[k][j];
    result.num[i][j] %= mod;
   }

  return result;
 }
};

//构造矩阵m,m[i][j]表示从状态i转移到状态j的方法数
void get_matrix( matrix& m )
{
 int i, j;

 for( i = 0; i < sz; ++i ) if( !word[i] )
 {
  for( j = 0; j < CH; ++j )
  {
   if( !word[chd[i][j]] )
    m.num[i][chd[i][j]]++;
  }
 }
}

int main()
{
 int m, n, i, ans = 0;
 char s[20];

 fail[0] = 0;
 sw['A'] = 0;
 sw['C'] = 1;
 sw['G'] = 2;
 sw['T'] = 3;
 memset(chd[0], 0, sizeof(chd[0]));
 
 scanf("%d %d", &m, &n);
 while( m-- )
 {
  scanf("%s", s);
  Ins(s);
 }
 AC();

 matrix mat( sz, sz );
 get_matrix( mat );
 matrix mm = mat;

 //矩阵幂乘
 --n;
 while( n )
 {
  if( n % 2 )
   mat = mat * mm;
  mm = mm * mm;
  n /= 2;
 }

 for( i = 0; i < sz; ++i )
  ans += mat.num[0][i];

 printf("%d\n", ans%mod);

 return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值