poj2778 DNA SequenceAC自动机矩阵快速幂
Posted wyboooo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj2778 DNA SequenceAC自动机矩阵快速幂相关的知识,希望对你有一定的参考价值。
DNA Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 19991 | Accepted: 7603 |
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
题意:
给定m个致病基因序列。问长度为n的DNA序列中有多少个是没有这些序列的。
思路:
这道题用到AC自动机的状态转移的性质了。
当我建好了状态图之后,在某一个状态a时,我可以知道他可以到达的所有状态。Trie树上的一个节点就是一个状态。
初始矩阵mat[i][j]表示的是从状态i走一步到状态j有几种可能。使用矩阵快速幂,对这个矩阵做n次幂,就可以得到每个两个状态之间走n次总共有多少方案。
对于一个长为n的串,没有任何一个致病基因序列,那么所有致病基因转移过去的状态都不能算进去。
我们给每一个致病基因做一个危险标记,同时要注意所有fail可以到达的节点如果是danger的,他自己也要变成danger
因为这段致病基因作为后缀出现在这个串中了。
1 #include <iostream> 2 #include <set> 3 #include <cmath> 4 #include <stdio.h> 5 #include <cstring> 6 #include <algorithm> 7 #include <vector> 8 #include <queue> 9 #include <map> 10 //#include <bits/stdc++.h> 11 using namespace std; 12 typedef long long LL; 13 #define inf 0x7f7f7f7f 14 15 int m, n; 16 const int maxn = 520; 17 const int maxlen = 2e6 + 5; 18 19 struct Matrix 20 { 21 unsigned long long mat[111][111]; 22 int n; 23 Matrix(){} 24 Matrix(int _n) 25 { 26 n=_n; 27 for(int i=0;i<n;i++) 28 for(int j=0;j<n;j++) 29 mat[i][j] = 0; 30 } 31 Matrix operator *(const Matrix &b)const 32 { 33 Matrix ret = Matrix(n); 34 for(int i=0;i<n;i++) 35 for(int j=0;j<n;j++) 36 for(int k=0;k<n;k++) 37 ret.mat[i][j]+=mat[i][k]*b.mat[k][j] % 100000; 38 return ret; 39 } 40 void print() 41 { 42 for(int i = 0; i < n; i++){ 43 for(int j = 0; j < n; j++){ 44 printf("%d ", mat[i][j]); 45 } 46 printf(" "); 47 } 48 } 49 }; 50 51 unsigned long long pow_m(unsigned long long a, int n) 52 { 53 unsigned long long ret = 1; 54 unsigned long long tmp = a; 55 while(n){ 56 if(n & 1)ret *= tmp; 57 tmp *= tmp; 58 n >>= 1; 59 } 60 return ret; 61 } 62 63 Matrix pow_M(Matrix a, int n) 64 { 65 Matrix ret = Matrix(a.n); 66 for(int i = 0; i < a.n; i++){ 67 ret.mat[i][i] = 1; 68 } 69 Matrix tmp = a; 70 //cout<<a.n<<endl; 71 while(n){ 72 if(n & 1)ret = ret * tmp; 73 tmp = tmp * tmp; 74 n >>= 1; 75 //ret.print(); 76 //cout<<endl; 77 } 78 return ret; 79 } 80 81 struct tree{ 82 int fail; 83 int son[4]; 84 bool danger; 85 }AC[maxlen]; 86 int tot = 0, id[130]; 87 char s[11]; 88 89 void build(char s[]) 90 { 91 int len = strlen(s); 92 int now = 0; 93 for(int i = 0; i < len; i++){ 94 int x = id[s[i]]; 95 if(AC[now].son[x] == 0){ 96 AC[now].son[x] = ++tot; 97 } 98 now = AC[now].son[x]; 99 } 100 AC[now].danger = true; 101 } 102 103 void get_fail() 104 { 105 queue<int>que; 106 for(int i = 0; i < 4; i++){ 107 if(AC[0].son[i] != 0){ 108 AC[AC[0].son[i]].fail = 0; 109 que.push(AC[0].son[i]); 110 } 111 } 112 while(!que.empty()){ 113 int u = que.front(); 114 que.pop(); 115 for(int i = 0; i < 4; i++){ 116 if(AC[u].son[i] != 0){ 117 AC[AC[u].son[i]].fail = AC[AC[u].fail].son[i]; 118 que.push(AC[u].son[i]); 119 } 120 else{ 121 AC[u].son[i] = AC[AC[u].fail].son[i]; 122 } 123 int x = AC[AC[u].son[i]].fail; 124 if(AC[x].danger){ 125 AC[AC[u].son[i]].danger = true; 126 } 127 } 128 } 129 } 130 131 /*int AC_query(char s[]) 132 { 133 int len = strlen(s); 134 int now = 0, cnt = 0; 135 for(int i = 0; i < len; i++){ 136 int x = id[s[i]]; 137 now = AC[now].son[x]; 138 for(int t = now; t; t = AC[t].fail){ 139 if(!AC[t].vis && AC[t].ed != 0){ 140 cnt++; 141 AC[t].vis = true; 142 } 143 } 144 } 145 return cnt; 146 }*/ 147 148 Matrix getMatrix() 149 { 150 Matrix ret = Matrix(tot + 1); 151 //int now = 0; 152 for(int i = 0; i < tot + 1; i++){ 153 if(AC[i].danger)continue; 154 for(int j = 0; j < 4; j++){ 155 if(AC[AC[i].son[j]].danger == false){ 156 ret.mat[i][AC[i].son[j]]++; 157 } 158 } 159 } 160 for(int i = 0; i < tot + 1; i++){ 161 ret.mat[i][tot] = 1; 162 } 163 return ret; 164 } 165 166 int main() 167 { 168 id[‘A‘] = 0;id[‘T‘] = 1;id[‘C‘] = 2;id[‘G‘] = 3; 169 //cout<<1<<endl; 170 while(~scanf("%d%d", &m, &n)){ 171 for(int i = 0; i <= tot; i++){ 172 AC[i].fail = 0; 173 AC[i].danger = false; 174 for(int j = 0; j < 4; j++){ 175 AC[i].son[j] = 0; 176 } 177 } 178 tot = 0; 179 for(int i = 1; i <= m; i++){ 180 scanf("%s", s); 181 build(s); 182 } 183 AC[0].fail = 0; 184 get_fail(); 185 Matrix mmm = Matrix(tot + 1); 186 //int now = 0; 187 for(int i = 0; i < tot + 1; i++){ 188 if(AC[i].danger)continue; 189 for(int j = 0; j < 4; j++){ 190 if(AC[AC[i].son[j]].danger == false){ 191 mmm.mat[i][AC[i].son[j]]++; 192 } 193 } 194 } 195 196 mmm = pow_M(mmm, n); 197 unsigned long long res = 0; 198 for(int i = 0; i < mmm.n; i++){ 199 res = (res + mmm.mat[0][i]) % 100000; 200 } 201 202 printf("%lld ", res); 203 } 204 //getchar(); 205 return 0; 206 }
以上是关于poj2778 DNA SequenceAC自动机矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章
poj 2778 DNA Sequence ac自动机+矩阵快速幂
POJ 2778 DNA Sequence(AC自动机+矩阵)