zoukankan      html  css  js  c++  java
  • POJ2778 DNA Sequence(AC自动机 矩阵)

    先使用AC自动机求得状态转移关系,再建立矩阵,mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数,则此矩阵的n次方表示n步从i,到j的方法数。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    typedef long long LL;
    const int N = 500, CH = 4;
    struct Trie{
        Trie *next[CH];
        Trie *fail;
        int cnt, id;
    }tree[N];
    
    int Hash[128];
    bool flag[1008];
    int chi[108][4];
    
    const LL MOD = 100000;
    int num;
    struct Mat{
        LL mat[108][108];
    
        Mat(){
            for(int i = 0; i <= num; i++){
                for(int j = 0; j <= num; j++){
                    mat[i][j] = 0;
                }
            }
        }
        Mat operator*(const Mat &b){
            Mat res;
            for(int i = 0;i <= num; i++){
                for(int j = 0; j <= num; j++){
                    for(int k = 0; k <= num; k++){
                        if(mat[i][k] == 0 || b.mat[k][j] == 0){
                            continue;
                        }
                        res.mat[i][j] += (mat[i][k] * b.mat[k][j])%MOD;
                    }
                    res.mat[i][j] %= MOD;
                }
            }
            return res;
        }
        Mat operator^(LL k){
            Mat res;
            Mat a = *this;
            for(int i = 0; i <= num; i++){
                res.mat[i][i] = 1;
            }
            while(k){
                if(k%2){
                    res = res * a;
                }
                a = a * a;
                k /= 2;;
            }
            return res;
        }
    };
    
    class ACauto{
        public:
        int nxt;
        Trie *root;
    
        ACauto(){
            root = &tree[0];
            nxt=0;
            memset(&tree[0], 0, sizeof(Trie));
        }
    
        void insert(char *s){
            Trie *p = root;
            for(int i = 0; s[i]; i++){
                int c = Hash[s[i]];
                if(!p -> next[c]){
                    memset(&tree[++nxt], 0, sizeof(Trie));
                    p -> next[c] = &tree[nxt];
                    p -> next[c] -> id = nxt;
                }
                p = p -> next[c];
            }
            p -> cnt++;
            flag[p -> id] = 1;
        }
    
        void build(){
            queue<Trie *> q;
            q.push(root);
            root -> fail = NULL;
            while(!q.empty()){
                Trie *cur = q.front();
                q.pop();
                //是否为终止结点
                if(cur ->fail && cur != root && flag[cur->fail->id]){
                    flag[cur->id] = 1;
                }
    
                for(int i = 0; i < CH; i++){
                    Trie *son = cur -> next[i];
                    Trie *tp = (cur == root)? root: cur -> fail->next[i];
                    if(son == NULL){
                        cur -> next[i] = tp;
                    }else{
                        son -> fail = tp;
                        q.push(son);
                    }
                    son = cur -> next[i];
                    //儿子节点
                    chi[cur -> id][i] = son -> id;
                }
            }
        }
    
    };
    
    char str[1008];
    int main(){
        Hash['A'] = 0;
        Hash['C'] = 1;
        Hash['G'] = 2;
        Hash['T'] = 3;
        int m;
        LL n;
        while(~scanf("%d %I64d", &m, &n)){
            ACauto ac;
            memset(flag, 0, sizeof(flag));
            memset(chi, -1, sizeof(chi));
            for(int i = 0; i < m; i++){
                scanf("%s", str);
                ac.insert(str);
            }
            ac.build();
            num = ac.nxt;
            Mat mt;
            //mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数
            for(int i = 0; i <= num ; i++){
                for(int j  = 0; j < 4; j++){
                    if(flag[chi[i][j]] == 0){
                        mt.mat[i][chi[i][j]]++;
                    }
                }
            }
            mt = mt ^ n;
            LL res = 0;
            for(int i = 0; i <= num; i++){
                res = (res + mt.mat[0][i]) % MOD;
            }
            printf("%I64d
    ", res);
    
        }
        return 0;
    }
    

      

  • 相关阅读:
    学习笔记——Maven实战(九)打包的技巧
    学习笔记——Maven实战(八)常用Maven插件介绍(下)
    学习笔记——Maven实战(七)常用Maven插件介绍(上)
    学习笔记——Maven实战(六)Gradle,构建工具的未来?
    学习笔记——Maven实战(五)自动化Web应用集成测试
    在Google的GKE上创建支持Internal Load Balancer的Service
    Bash命令查找本机公网IP
    Google Cloud IAM中添加自定义域名
    Debian上启用Apache2服务
    Google Cloud VM上在线扩硬盘
  • 原文地址:https://www.cnblogs.com/IMGavin/p/5809664.html
Copyright © 2011-2022 走看看