poj2778--DNA Sequence(AC自动机+矩阵优化)

http://blog.csdn.net/winddreams/article/details/43452145

DNA Sequence
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 12252 Accepted: 4661

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

 

给出患病的DNA序列,问序列长度为n的,且不包含患病的DNA序列有多少种。

首先处理患病的DNA串,连接为字典树后,添加fail指针,完成AC自动机,给每个节点一个编号,然后用矩阵统计每个节点走一步可以走到的节点的种数,其中,不能包含会患病的序列,最后矩阵相乘。

注意1.__int64 相乘会超出范围。

注意2.处理自动机时,注意,如果发现某个节点的fail会返回到一个代表序列结束的节点上,那么这个节点也是不可达的。不能被统计到矩阵中。

注意3.矩阵快速幂要写成非递归的形式。

给出测试案例:

2 1

ACG

C

其中矩阵应该为

2 1 0 0 0

2 1 0 0 0

0 0 0 0 0

0 0 0 0 0

0 0 0 0 0

[cpp]  view plain  copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <queue>  
  4. #include <algorithm>  
  5. using namespace std ;  
  6. #define MOD 100000  
  7. #define LL __int64  
  8. struct node{  
  9.     int flag , id ;  
  10.     node *next[4] , *fail ;  
  11. };  
  12. struct nnode{  
  13.     LL Map[110][110] , n ;  
  14. };  
  15. queue <node*> que ;  
  16. char c[5] = "ACGT" ;  
  17. char str[20] ;  
  18. int num , vis[110] ;  
  19. node *newnode()  
  20. {  
  21.     node *p = new node ;  
  22.     p->flag = 0 ;  
  23.     p->id = num++ ;  
  24.     p->fail = NULL ;  
  25.     for(int i = 0 ; i < 4 ; i++)  
  26.         p->next[i] = NULL ;  
  27.     return p ;  
  28. }  
  29. void settree(char *s,node *rt,int temp)  
  30. {  
  31.     int i , k , l = strlen(s) ;  
  32.     node *p = rt ;  
  33.     for(i = 0 ; i < l ; i++)  
  34.     {  
  35.         for(k = 0 ; k < 4 ; k++)  
  36.             if( s[i] == c[k] )  
  37.                 break ;  
  38.         if( p->next[k] == NULL )  
  39.             p->next[k] = newnode() ;  
  40.         p = p->next[k] ;  
  41.     }  
  42.     p->flag = 1 ;  
  43.     return ;  
  44. }  
  45. void setfail(node *rt)  
  46. {  
  47.     int i ;  
  48.     node *p = rt , *temp ;  
  49.     p->fail = NULL ;  
  50.     while( !que.empty() ) que.pop() ;  
  51.     que.push(p) ;  
  52.     while( !que.empty() )  
  53.     {  
  54.         p = que.front() ;  
  55.         que.pop() ;  
  56.         for(i = 0 ; i < 4 ; i++)  
  57.         {  
  58.             if( p->next[i] )  
  59.             {  
  60.                 temp = p->fail ;  
  61.                 while( temp && !temp->next[i] )  
  62.                     temp = temp->fail ;  
  63.                 p->next[i]->fail = temp ? temp->next[i] : rt ;  
  64.                 if( temp != NULL && temp->next[i]->flag )  
  65.                     p->next[i]->flag = 1 ;  
  66.                 que.push(p->next[i]) ;  
  67.             }  
  68.             else  
  69.                 p->next[i] = p == rt ? rt : p->fail->next[i] ;  
  70.         }  
  71.     }  
  72. }  
  73. nnode setmat(node *rt)  
  74. {  
  75.     int i , j , u , v ;  
  76.     nnode q ;  
  77.     node *p = rt ;  
  78.     while( !que.empty() ) que.pop() ;  
  79.     memset(q.Map,0,sizeof(q.Map)) ;  
  80.     memset(vis,0,sizeof(vis)) ;  
  81.     que.push(p) ;  
  82.     q.n = num ;  
  83.     vis[ p->id ] = 1 ;  
  84.     while( !que.empty() )  
  85.     {  
  86.         p = que.front() ;  
  87.         que.pop() ;  
  88.         u = p->id ;  
  89.         for(i = 0 ; i < 4 ; i++)  
  90.         {  
  91.             if( !p->flag && !p->next[i]->flag )  
  92.                 q.Map[ p->id ][ p->next[i]->id ]++ ;  
  93.             if( !vis[p->next[i]->id] )  
  94.             {  
  95.                 vis[ p->next[i]->id ] = 1 ;  
  96.                 que.push( p->next[i] ) ;  
  97.             }  
  98.         }  
  99.     }  
  100.     return q ;  
  101. }  
  102. nnode mul(nnode a,nnode b)  
  103. {  
  104.     nnode c ;  
  105.     c.n  = a.n ;  
  106.     int i , j , k ;  
  107.     for(i = 0 ; i < a.n ; i++)  
  108.     {  
  109.         for(j = 0 ; j < a.n ; j++)  
  110.         {  
  111.             c.Map[i][j] = 0 ;  
  112.             for(k = 0 ; k < a.n ; k++)  
  113.                 c.Map[i][j] = ( c.Map[i][j] + a.Map[i][k]*b.Map[k][j] ) % MOD ;  
  114.         }  
  115.     }  
  116.     return c ;  
  117. }  
  118. nnode pow(nnode p,int k)  
  119. {  
  120.     nnode temp ;  
  121.     int i , j ;  
  122.     temp.n = p.n ;  
  123.     memset(temp.Map,0,sizeof(temp.Map)) ;  
  124.     for(i = 0 ; i < p.n ; i++)  
  125.         temp.Map[i][i] = 1 ;  
  126.     while( k )  
  127.     {  
  128.         if( k&1 )  
  129.             temp = mul(temp,p) ;  
  130.         p = mul(p,p) ;  
  131.         k >>= 1 ;  
  132.     }  
  133.     return temp ;  
  134. }  
  135. int main()  
  136. {  
  137.     int n , m , i , j ;  
  138.     node *rt ;  
  139.     nnode p ;  
  140.     while( scanf("%d %d", &m, &n) != EOF )  
  141.     {  
  142.         num = 0 ;  
  143.         rt = newnode() ;  
  144.         for(i = 1 ; i <= m ; i++)  
  145.         {  
  146.             scanf("%s", str) ;  
  147.             settree(str,rt,i) ;  
  148.         }  
  149.         setfail(rt) ;  
  150.         p = setmat(rt) ;  
  151.         /*for(i = 0 ; i < p.n ; i++) 
  152.         { 
  153.             for(j = 0 ; j < p.n ; j++) 
  154.                 printf("%d ", p.Map[i][j]) ; 
  155.             printf("\n") ; 
  156.         }*/  
  157.         p = pow(p,n) ;  
  158.         LL ans = 0 ;  
  159.         for(i = 0 ; i < p.n ; i++)  
  160.             ans = ( ans + p.Map[0][i] ) % MOD ;  
  161.         printf("%d\n", ans) ;  
  162.     }  
  163.     return 0 ;  
  164. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值