pku 2778 DNA Sequence AC自动机 + 矩阵

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

题意:

给定n个病毒DNA串,求一个长度为m的DNA片段不包含任何一个病毒串的的可能数?

思路:
首先根据n个DNA串构造AC自动机,然后根据AC自动机构造矩阵,然后转化到Matrix大神的是个利用举证解决的问题的例八中去。

才开始我一直以为推出的举证和斐波那契数列的意思一样,转了个死弯,这里是把AC自动机这个图转化为邻接矩阵,然后求从一个状态到另一个状态经过m条边的的可能数。这个通过AC自动机得到的矩阵其实就是一个关系矩阵。

这里借鉴了一下胡浩大神的AC自动机模板:

//#pragma comment(linker,"/STACK:327680000,327680000")

#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <cstring>

#include <algorithm>

#include <string>

#include <set>

#include <functional>

#include <numeric>

#include <sstream>

#include <stack>

#include <map>

#include <queue>



#define CL(arr, val)    memset(arr, val, sizeof(arr))



#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define ll __int64

#define L(x)    (x) << 1

#define R(x)    (x) << 1 | 1

#define MID(l, r)   (l + r) >> 1

#define Min(x, y)   (x) < (y) ? (x) : (y)

#define Max(x, y)   (x) < (y) ? (y) : (x)

#define E(x)        (1 << (x))

#define iabs(x)     (x) < 0 ? -(x) : (x)

#define OUT(x)  printf("%I64d\n", x)

#define lowbit(x)   (x)&(-x)

#define Read()  freopen("din.txt", "r", stdin)

#define Write() freopen("dout.txt", "w", stdout);





#define M 150

#define N 1007

using namespace std;



const int MAX_NODE = 107;

const int CHILD_NUM = 4;

const int mod = 100000;



int n,m;

int sz;



struct Mat

{

    ll mat[MAX_NODE][MAX_NODE];

    void init()

    {

        CL(mat,0);

    }

}a;



Mat operator*(Mat a,Mat b)

{

    Mat c;

    int i,j,k;

    CL(c.mat,0);

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

    {

        for (j = 0; j < sz; ++j)

        {

            for (k = 0; k < sz; ++k)

            {

                if (!a.mat[i][k] || !b.mat[k][j]) continue;

                c.mat[i][j] += a.mat[i][k]*b.mat[k][j];

                if (c.mat[i][j] >= mod) c.mat[i][j] %= mod;

            }

        }

    }

    return c;

}

Mat operator^(Mat a,int k)

{

    Mat c;

    int i,j;

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

    {

        for (j = 0; j < sz; ++j)

        {

            c.mat[i][j] = (i == j);

        }

    }

    while (k)

    {

        if (k&1) c = c*a;

        k >>= 1;

        a = a*a;

    }

    return c;



}

class ACautomaton

{

    public:

    int chd[MAX_NODE][CHILD_NUM];

    int fail[MAX_NODE];

    int ID[128];

    int val[MAX_NODE];

    int Q[MAX_NODE];





    void Init()

    {

        fail[0] = 0;

        val[0] = 0;

        ID['A'] = 0; ID['G'] = 1;

        ID['C'] = 2; ID['T'] = 3;

    }

    void Reset()

    {

        CL(chd[0],0);

        sz = 1;

    }

    void insert(char *s,int key)

    {

        int k;

        int p = 0;

        for (; *s; s++)

        {

            k = ID[(int)*s];

            if (!chd[p][k])

            {

                CL(chd[sz],0);

                val[sz] = 0;

                chd[p][k] = sz++;

            }

            p = chd[p][k];

        }

        val[p] = 1;

    }

    void build()

    {

        int i;

        int *s = Q,*e = Q;

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

        {

            if (chd[0][i])

            {

                fail[chd[0][i]] = 0;

                *e++ = chd[0][i];

            }

        }

        while (s != e)

        {

            int u = *s++;

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

            {

                int &v = chd[u][i];

                if (v)

                {

                    *e++ = v;

                    fail[v] = chd[fail[u]][i];

                    val[v] |= val[fail[v]];

                }

                else

                {

                    v = chd[fail[u]][i];

                }

            }

        }

    }

    void Work()

    {

        int i,j;

        a.init();

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

        {

            if (val[i]) continue;

            for (j = 0; j < CHILD_NUM; ++j)

            {

                if (val[chd[i][j]]) continue;

                a.mat[i][chd[i][j]]++;

            }

        }

        Mat res;

        res = a^m;

        ll ans = 0;

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

        {

            if (val[i]) continue;

            ans += res.mat[0][i];

            ans %= mod;

        }

        printf("%I64d\n",ans%mod);

    }

}ac;



char str[15];



int main()

{

    int i;

    while (~scanf("%d%d",&n,&m))

    {

        ac.Init();

        ac.Reset();

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

        {

            scanf("%s",str);

            ac.insert(str,1);

        }

        ac.build();

        ac.Work();

    }

    return 0;

}

  

 

 

你可能感兴趣的:(sequence)