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

http://poj.org/problem?id=2778

DNA Sequence
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 14470   Accepted: 5579

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

问题大意:长度为n 由’A’‘G’‘C’‘T‘组成的字符串中不包含这m个字符串的任意一个的组合有多少种;

标记每个字符串的结尾节点为危险节点,如果失败后跳转到的节点是危险节点那么该节点也应为危险节点。

问题转化为长度问n不经过危险节点的走法有多少种。

构造矩阵mat,mat[i][j]为从第i个节点走一步到达第j个节点有多少种走法。求下mat的n次方,即求得ans[][],ans[i][j]为第i个节点走n步到达第j个节点的走法有多少种。

求下ans[0][i]的和就好。

理解好ac自动机和矩阵的含义后还是很好理解的。

后台数据比题意的数据要大一些。一开始一直wa,改了范围就A了。

#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#define maxx(a,b) ((a)>(b)?(a):(b))
#define F first
#define S second
using namespace std;

typedef  long long LL;
typedef unsigned long long  uLL;
const int  mod = 100000;
const LL  inf=0x3f3f3f3f;
//const double pi=acos(-1);
const int N=210;//最大点数
const int M=130;// 最大边数


int ans;
int bl[500];
struct mat
{
    int  v[210][210];
};
mat c,an;
int size_mat;
mat matrix_mul(mat p1,mat p2,int n,int m,int q)
{
    mat t;
    memset(t.v,0,sizeof(t.v));
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
            if(p1.v[i][j])
                for(int k=0; k<q; k++)
                {
                    int tep=((long long )p1.v[i][j]*p2.v[j][k])%mod;
                    t.v[i][k]=(t.v[i][k]+tep)%mod;
                }
    return t;
}
mat matrix_mi(mat p,int n,int k)
{
    mat t;
    memset(t.v,0,sizeof(t.v));
    for(int i=0; i<n; i++)
    {
        t.v[i][i]=1;
    }
    while(k)
    {
        if(k&1)
            t=matrix_mul(t,p,n,n,n);
            k>>=1;
        p=matrix_mul(p,p,n,n,n);
    }
    return t;
}
struct Trie
{
    int next[N][4],fail[N],end[N];
    int root,L;
    int nownode()
    {
        for(int i=0; i<4; i++)
            next[L][i]=-1;
        end[L++]=0;
        return L-1;
    }
    void init()
    {
        L=0;
        root=nownode();
    }
    void insert(char buf[],int k)
    {
        int len=strlen(buf);
        int  now=root;
        for(int i=0; i<len; i++)
        {
            if(next[now][bl[buf[i]]]==-1)
                next[now][bl[buf[i]]]=nownode();
            now=next[now][bl[buf[i]]];
        }
        end[now]=1;
    }
    void build()
    {
        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(end[fail[now]]==1)
                end[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]);
                }
            }
        }
    }
    int  gett()
    {
        for(int i=0; i<L; i++)
        {
            for(int j=0; j<4; j++)
            {
                if(end[next[i][j]]==0)
                    c.v[i][next[i][j]]++;
            }
        }
        return L;
    }
};
Trie ac;
char str[500];
int main()
{
#ifdef LOCAL
    freopen("date.in","r",stdin);
    freopen("date.out","w",stdout);
#endif
    int m,n;
    bl['A']=0;
    bl['G']=1;
    bl['C']=2;
    bl['T']=3;

    while(scanf("%d%d",&m,&n)!=EOF)
    {
        ac.init();
        for(int  i=1; i<=m; i++)
        {
            scanf("%s",str);
              ac.insert(str,i);
        }
         ac.build();
        memset(c.v,0,sizeof(c.v));
        size_mat=ac.gett();

        an=matrix_mi(c,size_mat,n);
        ans=0; 
        // for(int i=0;i<size_mat;i++)
        // {
        //     puts("");
        //     for(int j=0;j<size_mat;j++)
        //         printf("%d ",an.v[i][j]);
        // }
         for(int i=0;i<size_mat;i++)
         {
            ans+=an.v[0][i];
            ans%=mod;
         }
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(矩阵快速幂,AC自动机)