• POJ 2778 DNA Sequence [AC自动机 + 矩阵快速幂]


    http://poj.org/problem?id=2778
    题意:给一些只由ACGT组成的模式串,问有多少种长度为n且不含有给出的模式串的DNA序列。
    自动机的状态转换可以看成一个有向图(有重边的),该问题就转换成了在图上从0(trie树的根节点)开始走n步而不经过模式串末尾结点的路径数(重边算不同的路径)。
    有向图又可以用一个矩阵 M 表示出来,则 Mij 表示图中 ij 结点一步可达的路径数。 Mn 表示图中两点任意两点 n 步可达的路径数。
    如此,本题只需将 M 构造出来,再将 Mn 的第一行的和求出来就好了。要行走路径不经过模式串末尾点,也就是使那些顶点不可达,即它们对应的那些列都是0。 Mn 用矩阵快速幂可搞。

    #include<cassert>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<set>
    #include<queue>
    #include<map>
    using namespace std;
    #define rep(i,f,t) for(int i = (f), _end = (t); i <= _end; ++i)
    #define dep(i,f,t) for(int i = (f), _end = (t); i >= _end; --i)
    #define clr(c,x) memset(c,x,sizeof(c));
    #define debug(x) cout<<"debug  "<<x<<endl;
    const int INF = 0x3f3f3f3f;
    typedef long long int64;
    
    inline int RD(){ int res; scanf("%d",&res); return res; }
    
    #define Rush for(int casn = RD(), cas = 1; cas <= casn; ++cas)
    
    //********************************************************************
    
    typedef vector<int> Vec;
    typedef vector<Vec> Mat;
    
    const int mod = 100000;
    const int Len = 110;
    struct Trie{
        int next[Len][4];
        int fail[Len];
        int end[Len];
        int sz;
        void init(){
            sz = 0;
            clr(next[0], 0);
        }
        int idx(char c){
            if(c == 'A')return 0;
            if(c == 'C')return 1;
            if(c == 'T')return 2;
            return 3;
        }
        int newnode(){
            ++sz;
            clr(next[sz], 0);
            fail[sz] = end[sz] = 0;
            return sz;
        }
    
        void insert(char *s){
            int u = 0;
            while(*s){
                int nid = idx(*s++);
                int &v = next[u][nid];
                if(!v) v = newnode();
                u = v;
            }
            end[u] = 1;
        }
    
        void build(){
            queue<int> q;
            rep(c,0,3)if(next[0][c])q.push(next[0][c]);
            while(!q.empty()){
                int u = q.front();
                q.pop();
                int fu = fail[u];
                if(end[fu]) end[u] = 1;
                rep(c,0,3){
                    int &v = next[u][c];
                    if(v){
                        q.push(v);
                        fail[v] = next[fu][c];
                    }else{
                        v = next[fu][c];
                    }
                }
            }
        }
    
        void make(Mat &m){
            m.resize(sz+1);
            rep(i,0,sz)m[i].resize(sz+1);
            rep(u,0,sz)rep(c,0,3){
                int v = next[u][c];
                if(!end[v]) ++m[u][v];
            }
        }
    }ac;
    
    char str[15];
    
    Mat mul(const Mat &a,const Mat &b){
        Mat m( a.size(), Vec(b[0].size()) );
        rep(k,0,b.size()-1){
            rep(i,0,a.size()-1){
                if(!a[i][k])continue;
                rep(j,0,b[0].size()-1){
                    if(!b[k][j])continue;
                    m[i][j] = (m[i][j] + 1LL*a[i][k] * b[k][j] % mod) % mod;
                }
            }
        }
        return m;
    }
    Mat pow(Mat m, int b){
        Mat res(m.size(), Vec(m.size()));
        rep(i,0,res.size()-1) res[i][i] = 1;
    
        while(b){
            if(b&1){
                res = mul(res, m);
            }
            m = mul(m, m);
            b >>= 1;
        }
        return res;
    }
    
    int main(){
        int mi,n;
        while(~scanf("%d%d",&mi,&n)){
            ac.init();
            rep(i,1,mi){
                scanf("%s",str);
                ac.insert(str);
            }
            ac.build();
            Mat m;
            ac.make(m);
            Mat res = pow(m,n);
            int ans = 0;
            rep(j,0,res[0].size()-1){
                ans = (ans + res[0][j]) % mod;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Yarn调度器负载模拟器——Yarn Scheduler Load Simulator (SLS)
    代理模式之动态代理
    12.怎样自学Struts2发送邮件和验证补充[视频]
    jquery 深入学习笔记之中的一个 (事件绑定)
    IBM中国研究院、SAP、网易游戏、IBM2015应届生招聘笔试面试问题分享
    [LeetCode]Generate Parentheses
    oracle故障解决
    hdu 1065 I Think I Need a Houseboat
    hdu 1065 I Think I Need a Houseboat
    hdu 1237 简单计算器
  • 原文地址:https://www.cnblogs.com/DSChan/p/4861970.html
Copyright © 2020-2023  润新知