• POJ 2778 DNA Sequence (矩阵快速幂 + AC自动鸡)


    题目:传送门

    题意: 给你m个病毒串,只由(A、G、T、C) 组成, 问你生成一个长度为 n 的 只由 A、C、T、G 构成的,不包含病毒串的序列的方案数。

    解: 对 m 个病毒串,建 AC 自动机, 然后, 这个AC自动机就类似于一张有向图, 可以用邻接矩阵存这张有向图。

      最多10个病毒串, 每个病毒串长度不超过 10, 那最多是个 100 * 100 的矩阵, 可以接受。

       最后用矩阵快速幂加速推导。

      

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define LL long long
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define INF 0x3f3f3f3f
    #define inf 0x3f3f3f3f3f3f3f3f
    #define mem(i, j) memset(i, j, sizeof(i))
    #define pb push_back
    using namespace std;
    
    const int N = 111, mod = 100000;
    struct mat {
        LL a[N][N];
        mat() { mem(a, 0); }
    };
    struct Trie {
        int ch[N][30], tot, metch[N], Fail[N];
        void init() {
            mem(ch[0], 0); tot = 1; metch[0] = 0;
        }
        int get(char Q) {
            if(Q == 'A') return 0;
            else if(Q == 'C') return 1;
            else if(Q == 'T') return 2;
            return 3;
        }
        void join(char s[]) {
            int now = 0; int len = strlen(s);
            rep(i, 0, len - 1) {
                int id = get(s[i]);
                if(!ch[now][id]) {
                    mem(ch[tot], 0); metch[tot] = 0;
                    ch[now][id] = tot++;
                }
                now = ch[now][id];
            }
            metch[now] = 1;
        }
        void getFail() {
            queue<int> Q; while(!Q.empty()) Q.pop();
            rep(i, 0, 3) {
                if(ch[0][i]) {
                    Q.push(ch[0][i]); Fail[ch[0][i]] = 0;
                }
            }
            while(!Q.empty()) {
                int now = Q.front(); Q.pop();
                rep(i, 0, 3) {
                    int u = ch[now][i];
                    if(u == 0) ch[now][i] = ch[Fail[now]][i];
                    else {
                        Q.push(u);
                        Fail[u] = ch[Fail[now]][i];
                        metch[u] |= metch[Fail[u]];
                    }
                }
            }
        }
        mat getMat() {
            mat A;
            rep(i, 0, tot - 1) {
                if(metch[i]) continue;
                rep(j, 0, 3) {
                    if(!metch[ch[i][j]]) A.a[i][ch[i][j]]++;
                }
            }
            return A;
        }
    };
    Trie AC;
    char b[25];
    mat mul(mat A, mat B, int n) {
        mat C;
        rep(i, 0, n) {
            rep(j, 0, n) {
                rep(k, 0, n) {
                    C.a[i][j] = (C.a[i][j] + A.a[i][k] * B.a[k][j]) % mod;
                }
            }
        }
        return C;
    }
    mat ksm(mat A, int B, int n) {
        mat res; rep(i, 0, n) res.a[i][i] = 1;
        while(B) {
            if(B & 1) res = mul(res, A, n);
            A = mul(A, A, n); B >>= 1;
        }
        return res;
    }
    int main() {
        int n, m;
        while(~scanf("%d %d", &m, &n)) {
            AC.init();
            rep(i, 1, m) {
                scanf("%s", b); AC.join(b);
            }
            AC.getFail();
            mat A; A = AC.getMat();
            mat ans = ksm(A, n, AC.tot - 1);
            LL res = 0LL;
            rep(i, 0, AC.tot - 1) {
                res = (res + ans.a[0][i]) % mod;
            }
            printf("%lld
    ", res);
        }
        return 0;
    }
    View Code
    一步一步,永不停息
  • 相关阅读:
    java中的位运算符
    Servlet中的初始化参数、上下文参数、以及@Resource资源注入
    Servlet中文件上传的几种方式
    marquee标签的使用
    SpringBoot热部署的两种方式
    eclipse中安装lombok插件
    关于Servlet中的转发和重定项
    Cormen — The Best Friend Of a Man CodeForces 732B
    牛客小白月赛9之签到题
    Codeforces アンバランス / Unbalanced
  • 原文地址:https://www.cnblogs.com/Willems/p/12004676.html
Copyright © 2020-2023  润新知