zoukankan      html  css  js  c++  java
  • poj2778

    AC自动机+矩阵乘法

    套路$dp$,也就是从$root$开始走n步不经过危险节点

    这不就是经典的倍增$floyd$吗,trie图是有向图

    AC自动机真是个奇怪的东西,不能识别的子串都属于根节点

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int N = 105, P = 1e5;
    int n, m;
    int mp[N];
    char s[N];
    namespace ac 
    {
        int root, cnt;
        struct node {
            int ch[4];
            int fail, f;
        } t[N];
        void insert(char *s) {
            int len = strlen(s), now = root;
            for(int i = 0; i < len; ++i) {
                int &v = t[now].ch[mp[s[i]]];
                if(!v) {
                    v = ++cnt;
                }
                now = v;
            }
            t[now].f = 1;
        }
        void construct_fail() {
            queue<int> q;
            for(int i = 0; i < 4; ++i) {
                if(!t[root].ch[i]) {
        //            t[root].ch[i] = ++cnt;
                }
                if(t[root].ch[i]) {
                    q.push(t[root].ch[i]);
                }
            }
            while(!q.empty()) {
                int u = q.front();
                q.pop();
                for(int i = 0; i < 4; ++i) {
                    int &v = t[u].ch[i];
                    if(!v) {
                        v = t[t[u].fail].ch[i];
                    } else {
                        t[v].fail = t[t[u].fail].ch[i];
                        t[v].f |= t[t[v].fail].f;
                        q.push(v);
                    }
                }
            }
        }
    } using namespace ac;
    struct matrix {
        ll a[N][N];
        matrix() { memset(a, 0, sizeof(a)); }
        void set() {
            for(int i = 0; i <= cnt; ++i) {
                a[i][i] = 1;
            }
        }
        matrix friend operator * (const matrix &a, const matrix &b) {
            matrix ret;
            for(int k = 0; k <= cnt; ++k) {
                for(int i = 0; i <= cnt; ++i) {
                    for(int j = 0; j <= cnt; ++j) {
                        ret.a[i][j] = (ret.a[i][j] + a.a[i][k] * b.a[k][j] % P) % P;
                    }
                }
            }
            return ret;
        }
    } M, a;
    int main() {
        mp['A'] = 0;
        mp['G'] = 1;
        mp['C'] = 2;
        mp['T'] = 3;
        scanf("%d%d", &m, &n);
        for(int i = 1; i <= m; ++i) {
            scanf("%s", s);
            insert(s);
        }
        construct_fail();
        for(int i = 0; i <= cnt; ++i) {
            for(int j = 0; j < 4; ++j) {
                int v = t[i].ch[j];
                if(t[v].f) {
                    continue;
                }
                ++a.a[i][v];
            }
        }
        M.set();
        for(int i = n; i; i >>= 1, a = a * a) {
            if(i & 1) {
                M = M * a;
            }
        }
        ll ans = 0;
        for(int i = 0; i <= cnt; ++i) {
            ans = (ans + M.a[0][i]) % P;
        }
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    CVPR顶会热词统计
    @Annotation学习
    把一张表已有的数据对另一张表数据进行修改
    两张表数据不一致进行对比
    学习借鉴
    借鉴tcp
    借鉴tcp
    osi七层
    http学习
    Json学习
  • 原文地址:https://www.cnblogs.com/19992147orz/p/8480379.html
Copyright © 2011-2022 走看看