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

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

题意:有多少种长度n位DNA串不含有指定的病毒片段。

思路:首先,建立自动机,其实也就是一个有向图,则长度为n就好比是在图上走n次,也就是图对应矩阵的n次方。







const int mod=100000;

const int N=205;





struct node

{

    int next[4],fail,flag;



    void init()

    {

        clr(next,0);

        fail=-1;

        flag=0;

    }

};



node a[N];

int e,n,m;

char s[N];



int get(char x)

{

    if(x=='A') return 0;

    else if(x=='T') return 1;

    else if(x=='G') return 2;

    return 3;

}





void insert(char s[])

{

    int i,k,p=0;

    for(i=0;s[i];i++)

    {

        k=get(s[i]);

        if(a[p].next[k]==0)

        {

            a[e].init();

            a[p].next[k]=e++;

        }

        p=a[p].next[k];

    }

    a[p].flag=1;

}



queue<int> Q;



void build()

{

    Q.push(0);

    int i,j,k,p,q;

    while(!Q.empty())

    {

        k=Q.front();

        Q.pop();

        for(i=0;i<4;i++)

        {

            if(a[k].next[i])

            {

                p=a[k].next[i];

                q=a[k].fail;

                while(q!=-1&&!a[q].next[i]) q=a[q].fail;

                if(q==-1) a[p].fail=0;

                else

                {

                    a[p].fail=a[q].next[i];

                    a[p].flag|=a[a[p].fail].flag;

                }

                Q.push(p);

            }

            else

            {

                q=a[k].fail;

                while(q!=-1&&!a[q].next[i]) q=a[q].fail;

                if(q==-1) a[k].next[i]=0;

                else a[k].next[i]=a[q].next[i];

            }

        }

    }

}





int b[N][N],d[N][N];



void mul(int a[][N],int b[][N])

{

    int i,j,k,c[N][N]={0};

    FOR0(k,e) FOR0(i,e) FOR0(j,e)

    {

        c[i][j]+=(i64)a[i][k]*b[k][j]%mod;

        c[i][j]%=mod;

    }

    FOR0(i,e) FOR0(j,e) a[i][j]=c[i][j];

}



int main()

{

    RD(m,n);a[0].init();e=1;

    int i,j,k;

    FOR0(i,m)

    {

        RD(s);

        insert(s);

    }

    build();

    FOR0(i,e) if(!a[i].flag) FOR0(j,4)

    {

        k=a[i].next[j];

        if(!a[k].flag) b[i][k]++;

    }

    FOR0(i,e) d[i][i]=1;

    while(n)

    {

        if(n&1) mul(d,b);

        mul(b,b);

        n>>=1;

    }

    i64 ans=0;

    FOR0(i,e) if(!a[i].flag)ans+=d[0][i];

    ans%=mod;

    PR(ans);

}

  

你可能感兴趣的:(sequence)