码迷,mamicode.com
首页 > 其他好文 > 详细

poj2778

时间:2018-02-27 21:20:57      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:scanf   str   matrix   poj   floyd   continue   分享图片   name   push   

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\n", ans);
    return 0;
}
View Code

 

poj2778

标签:scanf   str   matrix   poj   floyd   continue   分享图片   name   push   

原文地址:https://www.cnblogs.com/19992147orz/p/8480379.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!