Fellow me on GitHub

POJ2778(SummerTrainingDay10-B AC自动机+矩阵快速幂)

DNA Sequence

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 17160   Accepted: 6616

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

Source

 
  1 //2017-08-10
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <queue>
  6 #define ll long long
  7 
  8 using namespace std;
  9 
 10 const int K = 4;
 11 const int N = 500010;
 12 const int M = 12;
 13 const int MOD = 100000;
 14 
 15 struct Matrix{  
 16     ll a[M*M][M*M];  
 17     int r, c; 
 18 }mat, tmp;  
 19 
 20 Matrix multi(Matrix x, Matrix y)//矩阵乘法
 21 {
 22     Matrix z;
 23     memset(z.a, 0, sizeof(z.a));  
 24     z.r = x.r, z.c = y.c;
 25     for(int i = 0; i < x.r; i++){
 26         for(int k = 0; k < x.c; k++)//加速优化
 27         {
 28             if(x.a[i][k] == 0) continue;
 29             for(int j = 0; j< y.c; j++)
 30                 z.a[i][j] = (z.a[i][j] + (x.a[i][k] * y.a[k][j]) % MOD) % MOD;
 31         }
 32     }
 33     return z;
 34 }
 35 
 36 void Matrix_pow(int n)//矩阵快速幂
 37 {  
 38     Matrix tmp;
 39     tmp.c = mat.c;
 40     tmp.r = mat.r;
 41     memset(tmp.a, 0, sizeof(tmp.a));
 42     for(int i = 0; i < tmp.c; i++)
 43         tmp.a[i][i] = 1;
 44     while(n){  
 45         if(n & 1)  
 46             tmp = multi(tmp, mat);  
 47         mat = multi(mat, mat);  
 48         n >>= 1;  
 49     }  
 50     int ans = 0;
 51     for(int i = 0; i < tmp.c; i++)
 52         ans = (ans + tmp.a[0][i]) % MOD;
 53     printf("%d\n", ans);
 54 }  
 55 
 56 struct AC_automation
 57 {
 58     //node nodes[N], *root, *superRoot, *cur;
 59     int nex[M*M][4], fail[M*M], match[M*M];
 60     int root, CNT;
 61     int newNode(){
 62         for(int i = 0; i < K; i++)
 63             nex[CNT][i] = -1;
 64         match[CNT++] = 0;
 65         return CNT-1;
 66     }
 67     int Hash(char ch)
 68     {
 69         if(ch == 'A')return 0;
 70         else if(ch == 'C')return 1;
 71         else if(ch == 'T')return 2;
 72         else if(ch == 'G')return 3;
 73     }
 74     void init(){
 75         CNT = 0;
 76         root = newNode();
 77     }
 78     void Insert(char s[]){//向字典树中插入一个字符串
 79         int n = strlen(s);
 80         int cur = root;
 81         for(int i = 0; i < n; i++){
 82             int p = Hash(s[i]);
 83             if(nex[cur][p] == -1)
 84                   nex[cur][p] = newNode();
 85             cur = nex[cur][p];
 86         }
 87         match[cur]++;
 88     }
 89     void build(){//构建自动机
 90         queue<int> que;
 91         fail[root] = root;
 92         for(int i = 0; i < K; i++){
 93             if(nex[root][i] == -1)
 94                 nex[root][i] = root;
 95             else{
 96                 fail[nex[root][i]] = root;
 97                 que.push(nex[root][i]);
 98             }
 99         }
100         while(!que.empty()){
101             int cur = que.front();
102             if(match[fail[cur]])match[cur] = 1;
103             que.pop();
104             for(int i = 0; i < K; i++){
105                 if(nex[cur][i] == -1){
106                     nex[cur][i] = nex[fail[cur]][i];
107                 }else{
108                     fail[nex[cur][i]] = nex[fail[cur]][i];
109                     que.push(nex[cur][i]);
110                 }
111             }
112         }
113     }
114     void to_marix(){
115         memset(mat.a, 0, sizeof(mat.a));
116         mat.r = mat.c = CNT;
117         for(int i = 0; i < CNT; i++){
118             for(int j = 0; j < 4; j++)
119                   if(!match[nex[i][j]])
120                     mat.a[i][nex[i][j]]++;
121         }
122         // for(int i = 0; i < CNT; i++){
123         //     for(int j = 0; j < CNT; j++)
124         //           cout<<mat.a[i][j]<<" ";
125         //     cout<<endl;
126         // }
127     }
128 };
129 
130 char str[M];
131 AC_automation ac;
132 
133 int main()
134 {
135     int n, m;
136     while(scanf("%d%d", &m, &n)!=EOF)
137     {
138         ac.init();
139         for(int i = 0; i < m; i++){
140             scanf("%s", str);
141             ac.Insert(str);
142         }
143         ac.build();
144         ac.to_marix();
145         Matrix_pow(n);
146     }
147 
148     return 0;
149 }

 

posted @ 2017-08-10 21:58  Penn000  阅读(177)  评论(0编辑  收藏  举报