您的位置:首页 > 产品设计 > UI/UE

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

2015-04-22 00:25 357 查看
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
先考虑一个简单的问题。

有向图,从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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: