poj2778 DNA Sequence【AC自动机】【矩阵快速幂】

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. 

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

题意:

给定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("\n");
 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\n", res);
203     }
204     //getchar();
205     return 0;
206 }

猜你喜欢

转载自www.cnblogs.com/wyboooo/p/9899944.html