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

Posted 既然选择了远方,便只顾风雨兼程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性代数(矩阵乘法):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 }

 

以上是关于线性代数(矩阵乘法):POJ 2778 DNA Sequence的主要内容,如果未能解决你的问题,请参考以下文章

DNA Sequence POJ - 2778 AC 自动机 矩阵乘法

POJ 2778 DNA Sequence (AC自动机,矩阵乘法)

[POJ2778]DNA Sequence

poj 2778 DNA Sequence ac自动机+矩阵快速幂

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

poj2778 DNA SequenceAC自动机矩阵快速幂