POJ 2778 DNA Sequence ( Trie图矩阵快速幂 )

Posted shuaihui520

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2778 DNA Sequence ( Trie图矩阵快速幂 )相关的知识,希望对你有一定的参考价值。

题意 : 给出一些病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个

 

分析:

我们先分析Tire 图的结构 : Trie图是在AC自动机的原型上增添边使得状态可以快速转移,标记危险的节点(后缀是不良单词的节点); 那我们是想构造长度是n不包含不良串对不对 , 那是不是在trie图上从0节点走n步到安全节点的方案数(Trie图也是状态转移图)

在一个有向图中,A走k步到B的方案数(这显然是经典的矩阵快速幂问题),(原理需要自己搜索)先对原图建立一个邻接表M[i][j] , M[i][j] =1表示i到j有边直接相连,然后ans=pow(M,k)  ,ans[A][B] 为答案

技术图片
#include<queue>
#include<stdio.h>
#include<string.h>
using namespace std;

const int Max_Tot = 1e2 + 10;
const int Letter  = 4;
const int MOD = 1e5;
int maxn;
int mp[128];

struct mat int m[111][111]; unit, M;

mat operator * (mat a, mat b)

    mat ret;
    long long x;
    for(int i=0; i<maxn; i++)
        for(int j=0; j<maxn; j++)
            x = 0;
            for(int k=0; k<maxn; k++)
                x += (long long)a.m[i][k]*b.m[k][j];
            
            ret.m[i][j] = x % MOD;
        
    
    return ret;


inline void init_unit()  for(int i=0; i<maxn; i++) unit.m[i][i] = 1; 

mat pow_mat(mat a, int n)

    mat ret = unit;
    while(n)
        if(n&1) ret = ret * a;
        a = a*a;
        n >>= 1;
    
    return ret;


struct Aho
    struct StateTable
        int Next[Letter];
        int fail, flag;
    Node[Max_Tot];
    int Size;
    queue<int> que;

    inline void init()
        while(!que.empty()) que.pop();
        memset(Node[0].Next, 0, sizeof(Node[0].Next));
        Node[0].fail = Node[0].flag = 0;
        Size = 1;
    

    inline void insert(char *s)
        int now = 0;
        for(int i=0; s[i]; i++)
            int idx = mp[s[i]];
            if(!Node[now].Next[idx])
                memset(Node[Size].Next, 0, sizeof(Node[Size].Next));
                Node[Size].fail = Node[Size].flag = 0;
                Node[now].Next[idx] = Size++;
            
            now = Node[now].Next[idx];
        
        Node[now].flag = 1;
    

//1) 如果son[i]不存在,将它指向 当前结点now的fail指针指
//向结点的i号后继(保证一定已经计算出来)。

//2) 如果son[i]存在,将它的fail指针指向 当前结点now的fail
//指针指向结点的i号后继(保证一定已经计算出来)。
    inline void BuildFail()
        Node[0].fail = 0;
        for(int i=0; i<Letter; i++)
            if(Node[0].Next[i])
                Node[Node[0].Next[i]].fail = 0;
                que.push(Node[0].Next[i]);
            else Node[0].Next[i] = 0;///必定指向根节点
        
        while(!que.empty())
            int top = que.front(); que.pop();
            if(Node[Node[top].fail].flag) Node[top].flag = 1;
            for(int i=0; i<Letter; i++)
                int &v = Node[top].Next[i];
                if(v)
                    que.push(v);
                    Node[v].fail = Node[Node[top].fail].Next[i];
                else v = Node[Node[top].fail].Next[i];
            
        
    

    inline void BuildMatrix()
        for(int i=0; i<Size; i++)
            for(int j=0; j<Size; j++)
                M.m[i][j] = 0;
        for(int i=0; i<Size; i++)
            for(int j=0; j<Letter; j++)
                if(!Node[i].flag && !Node[ Node[i].Next[j] ].flag)
                    M.m[i][Node[i].Next[j]]++;
            
        
        maxn = Size;
    

ac;

char S[11];
int main(void)

    mp[A]=0,
    mp[T]=1,
    mp[G]=2,
    mp[C]=3;
    int n, m;
    while(~scanf("%d %d", &m, &n))
        ac.init();
        for(int i=0; i<m; i++)
            scanf("%s", S);
            ac.insert(S);
        
        ac.BuildFail();
        ac.BuildMatrix();
//        for(int i=0; i<10; i++)
//            for(int j=0; j<10; j++)
//                printf("%d ", M.m[i][j]);
//            puts("");
//        puts("");

        init_unit();
        M = pow_mat(M, n);

//        for(int i=0; i<10; i++)
//            for(int j=0; j<10; j++)
//                printf("%d ", M.m[i][j]);
//            puts("");
//        puts("");

        int ans = 0;
        for(int i=0; i<ac.Size; i++)
            ans += M.m[0][i];
        ans %= MOD;
        printf("%d\n", ans);
    
    return 0;
View Code

 

以上是关于POJ 2778 DNA Sequence ( Trie图矩阵快速幂 )的主要内容,如果未能解决你的问题,请参考以下文章

POJ2778DNA Sequence(AC自动机)

POJ 2778 DNA Sequence (矩阵快速幂 + AC自动鸡)

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

POJ2778 DNA Sequence AC自动机上dp

POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)

DNA Sequence POJ - 2778 邻接矩阵 trie图 矩阵快速幂