poj 2778 DNA Sequence AC自动机DP 矩阵优化

DNA Sequence

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 11860 Accepted: 4527

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指针构造时没有即使break掉,另一点是tail标记上传时需要加入一个while循环。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 100
#define MAXT 100
#define MOD 100000
typedef long long qword;

struct trie_node
{
        int ptr[4];
        int fail;
        char w;
        bool tl;
}trie[MAXT];
int topt=1;
char str[MAXN];
void Add_word(char *str)
{
        int now=1;
        int ind;
        while (*str)
        {
                ind=*(str++)-'A';
                if (!trie[now].ptr[ind])
                {
                        trie[now].ptr[ind]=++topt;
                        trie[topt].w=ind+'A';
                        trie[topt].tl=false;
                }
                now=trie[now].ptr[ind];
        }
        trie[now].tl=true;
}
int q[MAXN];
void Build_Ac()
{
        int head=-1,tail=0;
        int now,temp;
        int i,j;
        q[0]=1;
        trie[1].fail=1;
        while (head<tail)
        {
                now=q[++head];
                for (i=0;i<4;i++)
                {
                        if (!trie[now].ptr[i])continue;
                        q[++tail]=trie[now].ptr[i];
                        if (now==1)
                        {
                                trie[trie[now].ptr[i]].fail=now;
                                continue;
                        }
                        temp=trie[now].fail;
                        while(temp!=1)
                        {
                                if (trie[temp].ptr[i])
                                {
                                        trie[trie[now].ptr[i]].fail=trie[temp].ptr[i];
                                        break;
                                }
                                temp=trie[temp].fail;
                        }
                        if (!trie[trie[now].ptr[i]].fail)
                                trie[trie[now].ptr[i]].fail=trie[1].ptr[i];
                        if (!trie[trie[now].ptr[i]].fail)
                                trie[trie[now].ptr[i]].fail=1;
                }
        }
        for (i=1;i<=topt;i++)
        {
                for (j=0;j<4;j++)
                {
                        if (!trie[i].ptr[j])
                        {
                                temp=trie[i].fail;
                                while (temp!=1)
                                {
                                        if (trie[temp].ptr[j])
                                        {
                                                trie[i].ptr[j]=trie[temp].ptr[j];
                                                break;
                                        }
                                        temp=trie[temp].fail;
                                }
                                if (!trie[i].ptr[j])
                                        trie[i].ptr[j]=trie[1].ptr[j];
                                if (!trie[i].ptr[j])
                                        trie[i].ptr[j]=1;
                        }
                }
        }
        j=3;
        while (j--)
        {
                for (i=0;i<=tail;i++)
                {
                        if (trie[trie[i].fail].tl)
                                trie[i].tl=true;
                }
        }
}
struct matrix
{
        int n,m;
        qword a[MAXN][MAXN];
        matrix()
        {
                memset(a,0,sizeof(a));
        }
        void pm()
        {
                int i,j;
                for (i=1;i<=n;i++)
                {
                        for (j=1;j<=m;j++)
                        {
                                printf("% 4d ",a[i][j]);
                        }
                        printf("\n");
                }
                printf("\n");
        }
}m1,r1,m2;
matrix operator *(matrix &m1,matrix &m2)
{
        if (m1.m!=m2.n)throw 1;
        matrix ret;
        ret.n=m1.n;
        ret.m=m2.m;
        int i,j,k;
        for (i=1;i<=ret.n;i++)
        {
                for (j=1;j<=ret.m;j++)
                {
                        for (k=1;k<=m1.m;k++)
                        {
                                ret.a[i][j]=(ret.a[i][j]+m1.a[i][k]*m2.a[k][j])%MOD;
                        }
                }
        }
        return ret;
}

int main()
{
        freopen("input.txt","r",stdin);
        //        freopen("output.txt","w",stdout);
        int n,m,i,j,k,x,y,z;
        scanf("%d%d\n",&m,&n);
        topt=1;
        trie[1].w='#';
        for (i=0;i<m;i++)
        {
                scanf("%s",str);
                x=strlen(str);
                for (j=0;j<x;j++)
                {
                        switch(str[j])
                        {
                                case 'A':str[j]='A';break;
                                case 'G':str[j]='B';break;
                                case 'C':str[j]='C';break;
                                case 'T':str[j]='D';break;
                        }
                }
                Add_word(str);
        }
        Build_Ac();
        m1.m=m1.n=topt;
        for (i=1;i<=topt;i++)
        {
                for (j=0;j<4;j++)
                {
                        if (trie[trie[i].ptr[j]].tl)continue;
                        m1.a[trie[i].ptr[j]][i]++;
                }
        }
        //        m1.pm();
        m2.m=1,m2.n=topt;
        m2.a[1][1]=1;
        while (n)
        {
                if (n&1)
                {
                        m2=m1*m2;
                }
                m1=m1*m1;
                n>>=1;
        }
        /*
        for (i=1;i<=n;i++)
        {
                m2=m1*m2;
                //        m2.pm();
        }*/
        qword ans=0;
        for (i=1;i<=topt;i++)
        {
                ans+=m2.a[i][1];
                ans%=MOD;
        }
        printf("%d\n",ans);
        return 0;
}

 

转载于:https://www.cnblogs.com/mhy12345/p/4045072.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值