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

来源:互联网 发布:坐标数据导入全站仪 编辑:程序博客网 时间:2024/06/02 02:09

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

Sample Output

36

先考虑一个简单的问题。

有向图,从i->j走n步的不同方法。构造矩阵,n次幂就是答案。

回到本题。自动机本身就是个有向图。那么去掉危险节点的n次幂

就是走构造长度为n的字符串的方法。

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<iostream>#include<queue>#include<cmath>#include<map>#include<stack>#include<bitset>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a )typedef long long LL;typedef pair<int,int>pil;const int INF = 0x3f3f3f3f;const int maxn=5500;const int MOD=1e5;int n,m,L;int ed[maxn];int next[maxn][26];int fail[maxn];struct Matrix{    LL mat[110][110];    void Clear()    {        CLEAR(mat,0);    }};struct AC{    int root;    int newnode()    {        for (int i = 0; i < 4; ++i)            next[L][i] = -1;        ed[L++] = 0;        return L - 1;    }    void init()    {        L = 0;        root = newnode();    }    int ID(char c)    {        if (c == 'A')            return 0;        if (c == 'G')            return 1;        if (c == 'C')            return 2;        if (c == 'T')            return 3;    }    void Insert(char buf[])    {        int now = root;        int len = strlen(buf);        for (int i = 0; i < len; ++i)        {            if (next[now][ID(buf[i])] == -1)                next[now][ID(buf[i])] = newnode();            now = next[now][ID(buf[i])];        }        ed[now] = 1;    }    void Build_AC()    {        queue<int>q;        fail[root]=root;        for(int i=0;i<4;i++)        {            if(next[root][i]==-1)                next[root][i]=root;            else            {                fail[next[root][i]]=root;                q.push(next[root][i]);            }        }        while(!q.empty())        {            int now=q.front();            q.pop();            if(ed[fail[now]])                ed[now]=1;            for(int i=0;i<4;i++)            {                if(next[now][i]==-1)                    next[now][i]=next[fail[now]][i];                else                {                    fail[next[now][i]]=next[fail[now]][i];                    q.push(next[now][i]);                }            }        }    }};Matrix mult(Matrix m1,Matrix m2){    Matrix ans;    for(int i=0;i<L;i++)    {        for(int j=0;j<L;j++)        {            ans.mat[i][j]=0;            for(int k=0;k<L;k++)                ans.mat[i][j]=(ans.mat[i][j]+m1.mat[i][k]*m2.mat[k][j])%MOD;        }    }    return ans;}Matrix Pow(Matrix m1,LL b){    Matrix ans;ans.Clear();    for(int i=0;i<L;i++)        ans.mat[i][i]=1;    while(b)    {        if(b&1)            ans=mult(ans,m1);        b>>=1;        m1=mult(m1,m1);    }    return ans;}void work(){    Matrix ans;    for(int i=0;i<L;i++)    {        if(ed[i])  continue;        for(int j=0;j<4;j++)        {            if(ed[next[i][j]])  continue;            ans.mat[i][next[i][j]]++;        }    }    ans=Pow(ans,m);    LL sum=0;    for(int i=0;i<L;i++)    {        if(!ed[i])        {            sum+=ans.mat[0][i];            sum%=MOD;        }    }    printf("%lld\n",sum);}AC A;int main(){    char str[15];    while(~scanf("%d%d",&n,&m))    {        A.init();        REPF(i,1,n)        {            scanf("%s",str);            A.Insert(str);        }        A.Build_AC();        work();    }    return 0;}


0 0