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

POJ Monthly--2006.03.26,dodo

题意:

给定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 }

原文地址:https://www.cnblogs.com/wyboooo/p/9899944.html

时间: 2024-11-10 06:51:46

poj2778 DNA Sequence【AC自动机】【矩阵快速幂】的相关文章

[poj2778]DNA Sequence(AC自动机+矩阵快速幂)

解题关键:卡时限过的,正在找原因中. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<queue> 8 using namespace std; 9 typedef long long ll; 10 cons

POJ POJ 2778 DNA Sequence AC自动机 + 矩阵快速幂

首先建立Trie和失败指针,然后你会发现对于每个节点 i 匹配AGCT时只有以下几种情况: i 节点有关于当前字符的儿子节点 j 且安全,则i 到 j找到一条长度为 1的路. i 节点有关于当前字符的儿子节点 j 且 不安全,则i 到 j没有路. i 节点没有关于当前字符的儿子节点 但是能通过失败指针找到一个安全的节点j,那么 i 到 j 找到一条长度为1的路. 关于节点安全的定义: 当前节点不是末节点且当前节点由失败指针指回跟节点的路径上不存在不安全节点,那么这个节点就是安全节点. 然后问题就

poj 2778 DNA Sequence(AC自动机+矩阵快速幂)

题目链接:poj 2778 DNA Sequence 题目大意:给定一些含有疾病的DNA序列,现在给定DNA长度,问有多少种不同的DNA序列是健康的. 解题思路:对DNA片段建立AC自动机,因为最多10个串,每个串最长为10,所以最多可能有100个节点,在长度为n时 以每个节点终止的健康字符串个数形成一个状态集,通过AC自动机形成的边可以推导出n+1的状态集,走到单词节点是 非法的,所以同样的我们可以先走到单词节点,但是从单词节点不向后转移.这样可以构造一个矩阵,剩下的就是矩阵 快速幂.注意的一

poj2778DNA Sequence (AC自动机+矩阵快速幂)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K 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 DN

hdu 2243 AC自动机 + 矩阵快速幂

// hdu 2243 AC自动机 + 矩阵快速幂 // // 题目大意: // // 给你一些短串,问在长度不超过k的任意串,包含至少一个这些短串的其中 // 一个.问这样的串有多少个. // // 解题思路: // // 首先, 包含和不包含是一种互斥关系,包含+不包含 = 全集u.全集的答案就是 // 26 ^ 1 + 26 ^ 2 + .... + 26 ^ k.不包含的比较好求.构建一个自动机,得到 // 一个转移矩阵A.表示状态i能到状态j的方法数.而这些状态中都是不包含所给的 //

HDU 2243 考研路茫茫――单词情结 (AC自动机 + 矩阵快速幂)

题目链接:考研路茫茫――单词情结 做本题前,个人建议先做一下POJ 2778 http://blog.csdn.net/u013446688/article/details/47378255 POJ2778 是求长度为n,不包含模式串的字符串个数. 而本题是求长度为n,包含模式串的字符串个数.直接用字符串总数减去不包含模式串的字符串个数即为所求. 同样是AC自动机 + 矩阵快速幂.但是还是有所不同的. 因为对2^64取模,所以定义数据类型为unsigned long long就可以了,这样就实现

poj 2778 AC自动机 + 矩阵快速幂

// poj 2778 AC自动机 + 矩阵快速幂 // // 题目链接: // // http://poj.org/problem?id=2778 // // 解题思路: // // 建立AC自动机,确定状态之间的关系,构造出,走一步 // 能到达的状态矩阵,然后进行n次乘法,就可以得到状态间 // 走n步的方法数. // 精髓: // 1):这个ac自动机有一些特别,根节点是为空串,然而 // 每走一步的时候,如果没法走了,这时候,不一定是回到根 // 节点,因为有可能单个的字符时病毒,这样

POJ 2778 DNA Sequence (AC自动机 + 矩阵快速幂)

题目链接:DNA Sequence 解析:AC自动机 + 矩阵加速(快速幂). 这个时候AC自动机 的一种状态转移图的思路就很透彻了,AC自动机就是可以确定状态的转移. AC代码: #include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; const int MOD = 100000; struct Matrix{ int ma

poj2778 ac自动机+矩阵快速幂

给m个子串,求长度为n的不包含子串的母串数,最直接的应该是暴搜,肯定tle,考虑用ac自动机 将子串建成字典树,通过next表来构造矩阵,然后用矩阵快速幂求长度为n的数量 邻接矩阵https://wenku.baidu.com/view/d7b9787f1711cc7931b716b0.html 对于a(i,j)^k  是指从i到j经过k个点的所有情况数 注意对于End数组,如果某个节点如果fail指针End数组为1,那么End[该节点]也是1 string要开全局变量,不然不能运行= = #i

POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂

这两题属于AC自动机的第二种套路通过矩阵快速幂求方案数. 题意:给m个病毒字符串,问长度为n的DNA片段有多少种没有包含病毒串的. 根据AC自动机的tire图,我们可以获得一个可达矩阵. 关于这题的tire图详解可以点击这里,往下面翻,这个博主的图对于tire图讲的非常详细. 知道了什么是tire图,理解了tire图后,后面的AC自动机的题目才能写. AC自动机的灵魂应该就是tire图 然后问题就变成了,得到了一个可达矩阵后,如何求方案数呢? 这个n = 2000000000 这咋办呢? 给定一