DNA Sequence

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9460   Accepted: 3545

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

 

 

题解:

先构建一颗trie树以及它的fail指针

然后给trie树的节点编号,代表这个状态的编号

然后构建一个邻接矩阵Map[i][j]代表从状态i变成状态j有多少种方法

初始化全为0

然后对树做一次dfs

假如 node->next[*]存在且不构成病毒片段(不是单词末尾) map[i][j]++ (i是node的状态编号,j是node->next[*]的状态编号)

如果node->next[*]不存在,就找node->fail->next[*]是否存在,存在就参考上一步,不存在就继续,直至root节点还没找到的话就是 map[i][0]++

 

现在我们就得到了一个表示状态转换的矩阵

题目的答案就是这个矩阵的N次幂

然后取从root可到的状态的方法总数即可

可参考http://hi.baidu.com/ccsu_010/item/7847a3c17f6fe2bc0d0a7b89

 

 

  1. #include <iostream> 
  2. #include <cstdio> 
  3. #include <cstring> 
  4. #define MOD 100000 
  5. #define size 200 
  6. using namespace std; 
  7. const int kind = 4; 
  8.  
  9. struct node  
  10.     node *fail; //失败指针 
  11.     node * next[kind]; //Tire每个节点的26个子节点(最多26个字母) 
  12.     int count; //是否为该单词的最后一个节点 
  13.     int state; 
  14.  
  15.     node() 
  16.     { //构造函数初始化 
  17.         fail = NULL; 
  18.         count = 0; 
  19.         memset(next, NULL, sizeof (next)); 
  20.     } 
  21. } *q[500001]; //队列,方便用于bfs构造失败指针 
  22.  
  23. char keyword[51]; //输入的单词 
  24. char str[1000001]; //模式串 
  25. int head, tail; //队列的头尾指针 
  26. int total; 
  27. long long map[200][200]; 
  28.  
  29. void insert(char *str, node *root)  
  30.     node *p = root; 
  31.     int i = 0, index; 
  32.     while (str[i])  
  33.     { 
  34.         if (str[i] == 'A') index = 0; 
  35.         if (str[i] == 'C') index = 1; 
  36.         if (str[i] == 'T') index = 2; 
  37.         if (str[i] == 'G') index = 3; 
  38.         if (p->next[index] == NULL) 
  39.         { 
  40.             p->next[index] = new node(); 
  41.             p->next[index]->state = total++; 
  42.         } 
  43.         p = p->next[index]; 
  44.         i++; 
  45.     } 
  46.     p->count++; 
  47.  
  48. void build_ac_automation(node *root)  
  49.     int i; 
  50.     root->fail = NULL; 
  51.     q[head++] = root; 
  52.     while (head != tail)  
  53.     { 
  54.         node *temp = q[tail++]; 
  55.         node *p = NULL; 
  56.         for (i = 0; i < kind; i++)  
  57.         { 
  58.             if (temp->next[i] != NULL)  
  59.             { 
  60.                 if (temp == root) 
  61.                     temp->next[i]->fail = root; 
  62.                 else  
  63.                 { 
  64.                     p = temp->fail; 
  65.                     while (p != NULL)  
  66.                     { 
  67.                         if (p->next[i] != NULL)  
  68.                         { 
  69.                             temp->next[i]->fail = p->next[i]; 
  70.                             if (p->next[i]->count != 0) 
  71.                                 temp->next[i]->count = p->next[i]->count; 
  72.                             break
  73.                         } 
  74.                         p = p->fail; 
  75.                     } 
  76.                     if (p == NULL) 
  77.                         temp->next[i]->fail = root; 
  78.                 } 
  79.                 q[head++] = temp->next[i]; 
  80.             } 
  81.         } 
  82.     } 
  83.  
  84. void build_matrix(node* now) 
  85.     if (now->count > 0) return ; 
  86.     for (int i = 0 ; i < kind ; i++) 
  87.     { 
  88.         if (now->next[i] != NULL) 
  89.         { 
  90.             if (now->next[i]->count == 0) 
  91.                 map[now->state][now->next[i]->state]++; 
  92.         } 
  93.         else 
  94.         { 
  95.             bool flag = false
  96.             node* temp = now; 
  97.             int temp_s = now->state; 
  98.             while (temp->next[i] == NULL && temp->fail != NULL) 
  99.             { 
  100.                 temp = temp->fail; 
  101.                 if (temp->next[i] != NULL) 
  102.                 { 
  103.                     if (temp->next[i]->count == 0) 
  104.                         map[temp_s][temp->next[i]->state]++; 
  105.                     flag = true
  106.                 } 
  107.                 if (temp->state == 0) break
  108.             } 
  109.             if (!flag) map[temp_s][0]++; 
  110.         } 
  111.     } 
  112.     for (int i = 0 ; i < kind ; i++) 
  113.         if (now->next[i] != NULL) build_matrix(now->next[i]); 
  114.  
  115. void MatrixMul(long long ans[size][size],long long cal[size][size]) 
  116.     long long temp[size][size]; 
  117.     for (int i = 0 ; i < total ; i++) 
  118.         for (int j = 0 ; j < total ; j++) 
  119.             temp[i][j] = 0; 
  120.     for (int i = 0 ; i < total ; i++) 
  121.         for (int j = 0 ; j < total ; j++) 
  122.             for (int k = 0 ; k < total ; k++) 
  123.             { 
  124.                 temp[i][j] += ans[i][k] * cal[k][j]; 
  125.                 if (temp[i][j] >= MOD) 
  126.                     temp[i][j] %= MOD; 
  127.             } 
  128.     for (int i = 0 ; i < total ; i++) 
  129.         for (int j = 0 ; j < total ; j++) 
  130.             ans[i][j] = temp[i][j]; 
  131.  
  132. void MatrixPow(long long ans[size][size],long long cal[size][size],int n) 
  133.     while (n > 0) 
  134.     { 
  135.         if (n&1) MatrixMul(ans,cal); 
  136.         MatrixMul(cal,cal); 
  137.         n >>= 1; 
  138.     } 
  139.  
  140. int main()  
  141.     int m,n; 
  142.     scanf("%d%d",&m,&n); 
  143.     total = 1; 
  144.     node *root = new node(); 
  145.     root->state = 0; 
  146.  
  147.     while (m--) 
  148.     { 
  149.         char s[20]; 
  150.         scanf("%s",s); 
  151.         insert(s,root); 
  152.     } 
  153.     build_ac_automation(root); 
  154.     for (int i = 0 ; i < total ; i++) 
  155.         for (int j = 0 ; j < total ; j++) 
  156.             map[i][j] = 0; 
  157.     build_matrix(root); 
  158.     long long ans[200][200]; 
  159.     for (int i = 0 ; i < total ; i++) 
  160.         for (int j = 0 ; j < total ; j++) 
  161.             ans[i][j] = 0; 
  162.     for (int i = 0 ; i < total ; i++) 
  163.         ans[i][i] = 1; 
  164.     MatrixPow(ans,map,n); 
  165.     long long out = 0; 
  166.     for (int i = 0 ; i < total ; i++) 
  167.         out = (out + ans[0][i]) % MOD; 
  168.     cout<<out<<endl; 
  169.     return 0;