• 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
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ng2-timesheet, 一个timesheet.js的angular2复制版
    Angular 2 + Electron 开发web和桌面应用
    Xamarin.Forms.Platform.Perspex, Xamarin Forms 的 Perspex(号称下一代WPF) 实现
    Visual Studio Xamarin编译Android项目出错的解决办法
    Salesforce + AngularJS + Bootstrap
    NativeScript 也能开发桌面应用 (nativescript-dotnet-runtime)
    iOS集成丁香园DXY OAuth 登陆 swift代码示例
    WinObjC?这是什么鬼?
    如何禁用Marlin温度保护
    React Native也正式发布了
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/11614994.html
Copyright © 2020-2023  润新知