线性代数(矩阵乘法):POJ 2778 DNA Sequence

DNA Sequence

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  思路是这样的:把所有病毒片段放入AC自动机中,建立fail数组。如果一个状态的fail为病毒节点,则他自己也为病毒节点。最后按边建矩阵,快速幂。
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 using namespace std;
  6 const int maxn=110;
  7 const int mod=100000;
  8 typedef unsigned long long ull;
  9 struct Matrix{
 10     int n;
 11     ull mat[maxn][maxn];
 12     Matrix(int n_,int on=0){
 13         n=n_;memset(mat,0,sizeof(mat));
 14         if(on)for(int i=1;i<=n;i++)mat[i][i]=1;
 15     }
 16     Matrix operator *(Matrix a){
 17         Matrix ret(n);
 18         unsigned long long l;
 19         for(int i=1;i<=n;i++)
 20             for(int k=1;k<=n;k++){
 21                 l=mat[i][k];
 22                 for(int j=1;j<=n;j++)
 23                     (ret.mat[i][j]+=l*a.mat[k][j]%mod)%=mod;
 24             }
 25         return ret;
 26     }
 27     Matrix operator ^(long long k){
 28         Matrix ret(n,1);
 29         while(k){
 30             if(k&1)
 31                 ret=ret**this;
 32             k>>=1;
 33             *this=*this**this;
 34         }
 35         return ret;
 36     }
 37 };
 38
 39 struct AC_automation{
 40     bool tag[maxn];
 41     int cnt,rt,ch[maxn][4],fail[maxn];
 42     AC_automation(){
 43         memset(tag,0,sizeof(tag));
 44         memset(fail,0,sizeof(fail));
 45         memset(ch,0,sizeof(ch));cnt=rt=1;
 46     }
 47
 48     int ID(char c){
 49         if(c==‘A‘)return 0;
 50         else if(c==‘C‘)return 1;
 51         else if(c==‘G‘)return 2;
 52         else return 3;
 53     }
 54
 55     void Insert(char *s){
 56         int len=strlen(s),p=rt;
 57         for(int i=0;i<len;i++)
 58             if(ch[p][ID(s[i])])
 59                 p=ch[p][ID(s[i])];
 60             else
 61                 p=ch[p][ID(s[i])]=++cnt;
 62         tag[p]=true;
 63     }
 64
 65     void Build(){
 66         queue<int>q;
 67         for(int i=0;i<4;i++)
 68             if(ch[rt][i])
 69                 fail[ch[rt][i]]=rt,q.push(ch[rt][i]);
 70             else
 71                 ch[rt][i]=rt;
 72
 73         while(!q.empty()){
 74             int x=q.front();q.pop();
 75             for(int i=0;i<4;i++)
 76                 if(ch[x][i]){
 77                     fail[ch[x][i]]=ch[fail[x]][i];
 78                     tag[ch[x][i]]|=tag[fail[ch[x][i]]];
 79                     q.push(ch[x][i]);
 80                 }
 81                 else
 82                     ch[x][i]=ch[fail[x]][i];
 83         }
 84     }
 85
 86     void Solve(int k){
 87         Matrix A(cnt);
 88         for(int i=1;i<=cnt;i++)
 89             for(int j=0;j<4;j++)
 90                 if(!tag[i]&&!tag[ch[i][j]])
 91                     A.mat[ch[i][j]][i]+=1;
 92         A=A^k;
 93         long long ans=0;
 94         for(int i=1;i<=cnt;i++)
 95             ans+=A.mat[i][1];
 96         printf("%lld\n",ans%mod);
 97     }
 98 }ac;
 99 char s[maxn];
100
101 int main(){
102 #ifndef ONLINE_JUDGE
103     //freopen("","r",stdin);
104     //freopen("","w",stdout);
105 #endif
106     int tot,n;
107     scanf("%d%d",&tot,&n);
108     while(tot--){
109         scanf("%s",s);
110         ac.Insert(s);
111     }
112     ac.Build();
113     ac.Solve(n);
114     return 0;
115 }
时间: 2024-10-17 12:32:00

线性代数(矩阵乘法):POJ 2778 DNA Sequence的相关文章

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

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

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自动机,矩阵乘法)

题意:给定n个不能出现的模式串,给定一个长度m,要求长度为m的合法串有多少种. 思路:用AC自动机,利用AC自动机上的节点做矩阵乘法. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<string> 6 #include<algorithm> 7 #include<queue> 8 #defin

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

POJ 2778 DNA Sequence

DNA Sequence Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: 277864-bit integer IO format: %lld      Java class name: Main It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's

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

题目链接:http://poj.org/problem?id=2778 题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) 思路:Trie图的状态转移,用矩阵mat[i][j]来表示从结点i到j只走一步有几种走法,那么mat的n次幂就表示从结点i到j走n步有几种走法,题目要求解的就是从头节点走n步且不包含危险结点的走法. mat = mat^n   ans = (mat[0][0] + mat[0][1] + ...

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

[题目链接] http://poj.org/problem?id=2778 [题目大意] 给出一些字符串,求不包含这些字符串的长度为n的字符串的数量 [题解] 我们将所有串插入自动机计算match,对于自动机上所有节点构建转移矩阵, 对于得到的可达矩阵我们求n长路的数量,统计0到各个点的n长路之和就是答案. [代码] #include <cstdio> #include <cstring> using namespace std; const int N=110; typedef

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自动机+矩阵快速幂)

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