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


    题目链接:http://poj.org/problem?id=2778

    题解:像这种能够找到长度为m的不包含子串的串有几种可以考虑用邻接矩阵,就是考虑从每一点出发走一次能够到达的位置,那么走两次能到达的位置就是矩阵的2次幂以此类推。于是可以利用自动机来得到矩阵然后就是矩阵快速幂。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <map>
    #define mod 100000
    using namespace std;
    typedef long long ll;
    const int M = 5e5 + 50;
    struct Matrix {
        ll dp[123][123];
    };
    Matrix Mul(Matrix a , Matrix b , int Max) {
        Matrix c;
        int i , j , k ;
        memset(c.dp , 0 , sizeof(c.dp));
        for(i = 0 ; i <= Max ; i++) {
            for(j = 0 ; j <= Max ; j++) {
                for(k = 0 ; k <= Max ; k++)
                    c.dp[i][j] = (a.dp[i][k] * b.dp[k][j] + c.dp[i][j]) % mod;
            }
        }
        return c ;
    }
    Matrix Matrix_quick_pow(Matrix a , int k , int Max) {
        Matrix res;
        memset(res.dp , 0 , sizeof(res.dp));
        for(int i = 0 ; i <= Max ; i++) res.dp[i][i] = 1;
        while(k) {
            if(k & 1) res = Mul(res , a , Max);
            k >>= 1;
            a = Mul(a , a , Max);
        }
        return res;
    }
    bool End[M];
    int Next[M][4] , fail[M] , root , L , cnt;
    int newnode() {
        for(int i = 0 ; i < 4 ; i++) {
            Next[L][i] = -1;
        }
        End[L++] = false;
        return L - 1;
    }
    void init() {
        L = 0;
        root = newnode();
    }
    void build(char s[]) {
        int len = strlen(s);
        int now = root;
        for(int i = 0 ; i < len ; i++) {
            int id = 0;
            if(s[i] == 'A') id = 0;
            if(s[i] == 'C') id = 1;
            if(s[i] == 'G') id = 2;
            if(s[i] == 'T') id = 3;
            if(Next[now][id] == -1) {
                Next[now][id] = newnode();
            }
            now = Next[now][id];
        }
        End[now] = true;
    }
    bool vis[123];
    queue<int>q;
    void get_fail() {
        while(!q.empty()) q.pop();
        fail[root]=root;
        for(int i = 0 ; i < 4 ; i++) {
            if(Next[root][i] == -1)
                Next[root][i] = root;
            else
            {
                fail[Next[root][i]] = root;
                q.push(Next[root][i]);
            }
        }
        while(!q.empty())
        {
            int now = q.front();
            q.pop();
            if(End[fail[now]]) End[now] = true;
            for(int i = 0 ; i < 4 ; i++) {
                if(Next[now][i] == -1)
                    Next[now][i] = Next[fail[now]][i];
                else
                {
                    fail[Next[now][i]] = Next[fail[now]][i];
                    q.push(Next[now][i]);
                }
            }
        }
    }
    Matrix a;
    Matrix getfair() {
        memset(a.dp , 0 , sizeof(a.dp));
        memset(vis , false , sizeof(vis));
        while(!q.empty()) q.pop();
        q.push(root);
        vis[root] = true;
        while(!q.empty()) {
            int now = q.front();
            q.pop();
            for(int i = 0 ; i < 4 ; i++) {
                if(!End[now] && !End[Next[now][i]]) a.dp[now][Next[now][i]]++;
                if(!vis[Next[now][i]]) vis[Next[now][i]] = true , q.push(Next[now][i]);
            }
        }
        return a;
    }
    char s[20];
    int main()
    {
        int n , m;
        while(~scanf("%d%d" , &n , &m)) {
            init();
            while(n--) {
                scanf("%s" , s);
                build(s);
            }
            get_fail();
            a = getfair();
            a = Matrix_quick_pow(a , m , L);
            ll ans = 0;
            for(int i = 0 ; i < L ; i++) {
                ans += a.dp[0][i];
                ans %= mod;
            }
            printf("%lld
    " , ans);
        }
        return 0;
    }
  • 相关阅读:
    linux-01-04(创建文件夹mkdir,进入目录命令cd,创建文件命令 echo cp vim touch等,批量创建文件操作)
    linux-05(tar命令的使用)
    linux-06(移动命令mv)
    linux-07(复制命令cp)
    linux-08(查看命令历史记录history)
    cookie
    vue-router路由懒加载
    setTimeout async promise执行顺序总结
    forEach陷阱
    函数节流与函数防抖之间的区别
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7345172.html
Copyright © 2020-2023  润新知