poj 2778 DNA Sequence

来源:互联网 发布:淘宝怎么能卖出东西 编辑:程序博客网 时间:2024/04/27 15:21

题目链接:http://poj.org/problem?id=2778

题目大意:问长度为N的串中不包含了模式串的串有几个。

题目思路:求长度为n的不含病毒串的字符串个数,用ac自动机构造转移矩阵,再用二分幂计算即可。需要注意的是尽量不用模运算,模运算实在是太慢了。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#include<queue>#include<algorithm>#include<vector>#include<stack>#include<list>#include<iostream>#include<map>using namespace std;#define inf 0x3f3f3f3f#define Max 110#define mod 100000int max(int a,int b){return a>b?a:b;}int min(int a,int b){return a<b?a:b;}int q[12*12];int a[120][120],b[120][120];__int64 c[120][120];int cnt;char s[12];int ans;int mp[256];int hash[200];struct node{    int cnt,fail;    int next[4];    void init()    {        cnt=fail=0;        memset(next,0,sizeof(next));    }}tri[12*12];void insert(char *s){    int p,x,i;    p=0;    for(i=0;s[i];i++)    {        x=mp[s[i]];        if(!tri[p].next[x])        {            tri[++cnt].init();            tri[p].next[x]=cnt;        }        p=tri[p].next[x];    }    tri[p].cnt++;}void bfs(){    int i,p,suf,head=0,tail=0;    p=0;    for(i=0;i<4;i++)    {        if(tri[0].next[i])        {            q[tail++]=tri[0].next[i];            tri[q[tail-1]].fail=0;        }    }    while(head<tail)    {        p=q[head++];suf=tri[p].fail;        if(tri[suf].cnt)            tri[p].cnt=1;        for(i=0;i<4;i++)        {            if(tri[p].next[i])            {                q[tail++]=tri[p].next[i];                tri[q[tail-1]].fail=tri[suf].next[i];            }            else                tri[p].next[i]=tri[suf].next[i];        }    }    memset(b,0,sizeof(b));    int rec=0;    for(i=0;i<=cnt;i++)    {        if(!tri[i].cnt)            hash[i]=rec++;    }    for(i=0;i<=cnt;i++)    {        if(tri[i].cnt)            continue;        for(int j=0;j<4;j++)        {            int tmp=tri[i].next[j];            if(!tri[tmp].cnt)            b[hash[i]][hash[tmp]]++;        }    }     cnt=rec-1;}inline void run(int a[][120],int b[][120],__int64 c[][120]){    int i,j,k;    for(i=0;i<=cnt;i++)        for(j=0;j<=cnt;j++)        {            c[i][j]=0;            for(k=0;k<=cnt;k++)                c[i][j]+=((__int64)a[i][k]*b[k][j]);            c[i][j]%=mod;        }    for(i=0;i<=cnt;i++)        for(j=0;j<=cnt;j++)            a[i][j]=c[i][j];}void solve(int n){    memset(a,0,sizeof(a));    a[0][0]=1;    while(n)    {        if(n&1)            run(a,b,c);        n>>=1;        run(b,b,c);    };    for(int i=0;i<=cnt;i++)        ans+=a[0][i];    ans%=mod;}int main(){    int m,n;    mp['A']=0;mp['C']=1;mp['G']=2;mp['T']=3;    while(scanf("%d%d",&m,&n)!=EOF)    {        ans=0;        cnt=0;        tri[0].init();        while(m--)        {            scanf("%s",s);            insert(s);        }        bfs();        solve(n);        printf("%d\n",ans);    }}


 

原创粉丝点击