zoukankan      html  css  js  c++  java
  • POJ-2778-DNA Sequence(AC自动机, 矩阵快速幂)

    链接:

    https://vjudge.net/problem/POJ-2778

    题意:

    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.

    思路:

    我们把病毒序列做成一个Trie图, 我们就是在这个有向图上走n步能构成多少个字符串.
    考虑某些结尾的点不能走, 因为走到了就形成了病毒序列, 同时某个节点的Fail指针指向的节点是病毒结尾节点这个点同样不能走.以为走到了, 形成的后缀中就存在病毒序列.
    吧所有能走的点列成一个矩阵, 同时先求出走一步的矩阵, 考虑从a->b, 就是a->x, x->b,可以通过矩阵乘法求出所有a->b的方法.
    考虑矩阵快速幂.
    代码偷懒直接重载运算符写法.
    再上一个大佬题解(特别清晰):https://blog.csdn.net/morgan_xww/article/details/7834801

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    //#include <memory.h>
    #include <queue>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <math.h>
    #include <stack>
    #include <string>
    #include <assert.h>
    #include <iomanip>
    #include <iostream>
    #include <sstream>
    #define MINF 0x3f3f3f3f
    using namespace std;
    typedef long long LL;
    const int MOD = 1e5;
    const int MAXN = 2e6+10;
    
    struct AcTree
    {
        int Next[4];
        int fail;
        int end;
        int ok;
        void Init()
        {
            memset(Next, 0, sizeof(Next));
            end = 0;
            fail = 0;
            ok = 1;
        }
    }tree[MAXN];
    struct Martix
    {
        LL mar[110][110];
        int n;
        void Inin(const int *key, int len, const int *value)
        {
            memset(mar, 0, sizeof(mar));
            n = len;
            for (int i = 1;i <= n;i++)
            {
                for (int j = 0;j < 4;j++)
                {
                    int node = tree[key[i]].Next[j];
                    if (tree[node].ok == 0)
                        continue;
                    mar[i][value[node]]++;
    //                cout << key[i] << ' ' << node << endl;
                }
            }
        }
        Martix& operator * (const Martix& that)
        {
            LL tmp[110][110];
            for (int i = 1;i <= n;i++)
            {
                for (int j = 1;j <= n;j++)
                {
                    LL tmpval = 0;
                    for (int k = 1;k <= n;k++)
                        tmpval = (tmpval+(this->mar[i][k]*that.mar[k][j])%MOD)%MOD;
                    tmp[i][j] = tmpval;
                }
            }
            for (int i = 1;i <= n;i++)
            {
                for (int j = 1;j <= n;j++)
                    this->mar[i][j] = tmp[i][j];
            }
            return *this;
        }
    }Mar;
    map<char, int> Mp;
    char s[MAXN];
    int Key[110], Value[110*110];
    LL n, m, cnt;
    
    void Insert(char *s)
    {
        int len = strlen(s);
        int pos = 0;
        for (int i = 0;i < len;i++)
        {
            if (tree[pos].Next[Mp[s[i]]] == 0)
            {
                tree[pos].Next[Mp[s[i]]] = ++cnt;
                tree[cnt].Init();
            }
            pos = tree[pos].Next[Mp[s[i]]];
        }
        tree[pos].end = 1;
        tree[pos].ok = 0;
    }
    
    void BuildAC()
    {
        queue<int> que;
        for (int i = 0;i < 4;i++)
        {
            if (tree[0].Next[i] != 0)
                tree[tree[0].Next[i]].fail = 0, que.push(tree[0].Next[i]);
    
        }
        while (!que.empty())
        {
            int u = que.front();
            que.pop();
            if (tree[tree[u].fail].ok == 0)
                tree[u].ok = 0;
            for (int i = 0;i < 4;i++)
            {
                if (tree[u].Next[i] != 0)
                {
                    tree[tree[u].Next[i]].fail = tree[tree[u].fail].Next[i];
                    que.push(tree[u].Next[i]);
                }
                else
                    tree[u].Next[i] = tree[tree[u].fail].Next[i];
            }
        }
    }
    
    Martix QuickMartixMi(Martix a, LL b)
    {
        b--;
        Martix res = a;
        while (b)
        {
            if (b&1)
                res*a;
            a*a;
            b >>= 1;
        }
        return res;
    }
    
    int main()
    {
        Mp['A'] = 0;
        Mp['T'] = 1;
        Mp['G'] = 2;
        Mp['C'] = 3;
        while(~scanf("%d%d", &m, &n))
        {
            cnt = 0;
            tree[0].Init();
            for (int i = 1; i <= m; i++)
            {
                scanf("%s", s);
                Insert(s);
            }
            BuildAC();
            int tmp = 0;
            for (int i = 0;i <= cnt;i++)
            {
                if (tree[i].ok)
                    Key[++tmp] = i, Value[i] = tmp;
            }
            Mar.Inin(Key, tmp, Value);
            Martix res = QuickMartixMi(Mar, n);
            LL ans = 0;
            for (int i = 1;i <= res.n;i++)
                ans = (ans+res.mar[1][i])%MOD;
            printf("%lld
    ", ans);
        }
    
        return 0;
    }
    
  • 相关阅读:
    原型与继承
    sqlserver优化管理
    vue 错误拦截
    axios 重新发起上次请求
    vue 滚动加载数据
    el-scrollbar组件
    ES服务器优化
    Aspose 生成pdf行距的不正确的问题,行距变高
    DocumentFormat.OpenXml.dll通過word做好的模板生成word
    stm32f103 rt-thread fal easyflash移植过程
  • 原文地址:https://www.cnblogs.com/YDDDD/p/11632892.html
Copyright © 2011-2022 走看看