DNA Sequence(POJ2778 AC自动机dp+矩阵加速)

传送门

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

裸ac自动机。。写出原dp。。构造出矩阵即可。。

  1 #include<set>
  2 #include<map>
  3 #include<queue>
  4 #include<cstdio>
  5 #include<cstdlib>
  6 #include<cstring>
  7 #include<iostream>
  8 #include<algorithm>
  9 using namespace std;
 10 const int SONS=4;
 11 const int MOD=100000;
 12 const char Hash[5]={‘ ‘,‘A‘,‘C‘,‘T‘,‘G‘};
 13 #define For(i,n) for(int i=1;i<=n;i++)
 14 #define For0(i,n) for(int i=0;i<n;i++)
 15 #define Rep(i,l,r) for(int i=l;i<=r;i++)
 16 #define Down(i,r,l) for(int i=r;i>=l;i--)
 17
 18 struct trie{
 19     int sz,ch[11*11][SONS],fn[11*11],next[11*11],q[11*11*3];
 20     trie(){sz=0;}
 21     void insert(char *s){
 22         int cur=0,len=strlen(s),id;
 23         For0(i,len){
 24             For(j,4) if(s[i]==Hash[j]){id=j-1;break;}
 25             if(!ch[cur][id]) ch[cur][id]=++sz;
 26             cur=ch[cur][id];
 27         }
 28         fn[cur]=1;
 29     }
 30     void BuildAC(){
 31         int l=0,r=0;
 32         For0(i,SONS)
 33           if(ch[0][i]) q[++r]=ch[0][i];
 34         while(l<r){
 35             int cur=q[++l];
 36             For0(i,SONS){
 37                 if(ch[cur][i]){
 38                     q[++r]=ch[cur][i];
 39                     next[ch[cur][i]]=ch[next[cur]][i];
 40                     if(fn[next[ch[cur][i]]]) fn[ch[cur][i]]=1;
 41                 }
 42                 else ch[cur][i]=ch[next[cur]][i];
 43             }
 44         }
 45     }
 46 }ac;
 47
 48 int m,n,ans,dp[121][121];
 49 char st[11];
 50
 51 struct Matrix{
 52     int A[11*11][11*11];
 53     Matrix(){memset(A,0,sizeof(A));}
 54 }Unit,Ans;
 55
 56 Matrix operator * (Matrix A,Matrix B){
 57     Matrix C;
 58     For0(i,ac.sz+1)
 59       For0(j,ac.sz+1)
 60         For0(k,ac.sz+1)
 61           C.A[i][j]=(C.A[i][j]+(long long)A.A[i][k]*B.A[k][j])%MOD;
 62     return C;
 63 }
 64
 65 void DP(){
 66     For0(i,ac.sz+1)
 67         if(!ac.fn[i])
 68           For0(k,SONS){
 69               int cur=ac.ch[i][k];
 70               if(!ac.fn[cur]) Unit.A[i][cur]++;
 71           }
 72     For0(i,ac.sz+1) Ans.A[i][i]=1;
 73     while(n){
 74         if(n&1) Ans=Ans*Unit;
 75         Unit=Unit*Unit;
 76         n>>=1;
 77     }
 78     For0(i,ac.sz+1) ans=(ans+Ans.A[0][i])%MOD;
 79     printf("%d\n",ans%MOD);
 80     /*dp[0][0]=1;
 81     For(i,n)
 82       For0(j,ac.sz+1){
 83           if(ac.fn[j]) continue;
 84           For0(k,SONS){
 85               int cur=ac.ch[j][k];
 86               if(ac.fn[cur]) continue;
 87               dp[i][cur]=(dp[i][cur]+dp[i-1][j])%MOD;
 88           }
 89       }
 90     For0(i,ac.sz+1) if(!ac.fn[i]) ans=(ans+dp[n][i])%MOD;
 91     printf("%d\n",ans);*/
 92 }
 93
 94 int main(){
 95     scanf("%d%d",&m,&n);
 96     For(i,m){
 97         scanf("%s",&st);
 98         ac.insert(st);
 99     }
100     ac.BuildAC();
101     DP();
102     return 0;
103 }
时间: 2024-10-20 22:44:17

DNA Sequence(POJ2778 AC自动机dp+矩阵加速)的相关文章

[POJ2778]DNA Sequence(AC自动机 + DP + 矩阵优化)

传送门 AC自动机加DP就不说了 注意到 m <= 10,所以模式串很少. 而 n 很大就需要 log 的算法,很容易想到矩阵. 但是该怎么构建? 还是矩阵 A(i,j) = ∑A(i,k) * A(k,j),那么i到j的方案数就是j到k的方案数称k到j的方案数,那么直接矩阵快速幂即可 #include <queue> #include <cstdio> #include <cstring> #define N 100001 #define p 100000 #d

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理)

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理) 题意:给出若干个模式串,总长度不超过40,对于某一个字符串,它有一个价值,对于这个价值的计算方法是这样的,设初始价值为V=1,假如这个串能匹配第k个模式串,则V=V*prime[k]*(i+len[k]),其中prime[k]表示第k个素数,i表示匹配的结束位置,len[k]表示第k个模式串的长度(注意,一个字符串可以多次匹配同意个模式串).问字符集为'A'-'Z'的字符,组成的所有的长为L的字符串,

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

距离上次做AC自动机有很久了=.=,以前这题的思路死活看不懂,现在还是觉得很好理解的. 思路参见:http://blog.csdn.net/morgan_xww/article/details/7834801#. 我用cnt=1表示这个节点是危险的,然后再匹配fail指针的时候,如果一个节点的前缀是危险的,那么这个节点也是危险的,这么维护即可. 顺便一提,我以前的AC自动机模板是没有build过程中失配时的nxt指针的(以前是在match的过程中体现),但是失败时候需要的nxt指针又是很好用的,

HDU2457 DNA repair(AC自动机+DP)

题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步)且后缀状态为AC自动机结点j的最少需要修改的基因数 转移我为人人型,从dp[i][j]向ATCG四个方向转移到dp[i+1][j'],如果结点被标记包含致病基因就不能转移. 1 #include<cstdio> 2 #include<cstring> 3 #include<que

HDU 2457 DNA repair (AC自动机 + DP)

题目链接:DNA repair 解析:给出n个致病DNA序列,给一段DNA片段,问最少修改多少个碱基才能修复这段DNA序列中的所有致病序列. AC自动机 + DP. 将n个致病DNA序列构成一个自动机. 令DP[i][j]表示长度为i走到节点j是所需改变的最少个数. 状态转移时,枚举下一步所有可能的碱基,然后判断该碱基是否达到匹配状态,若能,则安全转移,继续枚举下一个碱基:否则在不匹配的前提下,看该碱基加入之后是否跟上一状态相同,若不同,则需修复,即计数加一.若相同,直接转移即可.然后选择其中最

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 ex

【POJ2778】DNA Sequence(AC自动机)

题意: 生物课上我们学到,DNA序列中只有A, C, T和G四种片段. 经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段"ATC"是不好片段,则"AGATCC", "CATCAA", "ATCATC"都是不好的DNA序列,这些不好片段我们可以称为病毒片段. 现在已知m个病毒片段, 问长度为n的DNA序列,有多少种可能不包含病毒片段.答案可能很大,取模 100000. [数据规模和约定] 0<=m<=1

POJ 2778 DNA Sequence(AC自动机确定DFA转移图+矩阵快速幂)

这道题极好的展示了AC自动机在构造转移图DFA上的应用 DFA转移图就是展示状态的转移过程的图,DFA图构造出来后就可以用DP求出任何DNA长度下,任何状态的个数 本题用自动机求出DFA矩阵,那么有 | dp[n][0] dp[n][1] ... dp[n][m] |=|dp[1][0] dp[1][1] ... dp[1][m] | * DFA^(n-1)    (m指状态总数) DP边界矩阵|dp[1][0] dp[1][1] ... dp[1][m] | 也就是DFA的第一行,所以dp[n

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