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.
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
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 }