POJ

来源:互联网 发布:上海知而行 编辑:程序博客网 时间:2024/06/03 19:31

题意

给出 m 个遗传病DNA片段(长度不大于10),再给一个整数 n 。问长度不超过 n 的DNA中有多少个不含有遗传病。

思路

链接

https://vjudge.net/contest/177933#problem/B

代码

#include<cstdio>#include<iostream>#include<cstring>#include<queue>#include<vector>using namespace std;const int maxn = 120;const int kind = 4;int trie[maxn][kind], tt;bool du[maxn];int fail[maxn];int id[100];int m, n;char str[15];const int mod = 100000;typedef long long LL;LL mat0[maxn][maxn], mat1[maxn][maxn], mat2[maxn][maxn];LL (*m0)[maxn], (*m1)[maxn], (*m2)[maxn];void ins(char s[], int root){    int i = 0, p = root;    while(str[i] != '\0')    {        if(trie[p][id[str[i]]] == -1) trie[p][id[str[i]]] = ++tt;        p = trie[p][id[str[i]]];        i++;    }    du[p] = true;}void build_ac_automation(int root){    queue<int> qu;    fail[0] = 0;    for(int i = 0; i < kind; i++)    {        if(trie[0][i] != -1)        {            fail[trie[0][i]] = 0;            qu.push(trie[0][i]);        }        else trie[0][i] = 0;    }    while(qu.size())    {        int v = qu.front();        qu.pop();        if(du[fail[v]]) du[v] = true;        for(int i = 0; i < kind; i++)        {            int &u = trie[v][i];            if(u != -1)            {                fail[u] = trie[fail[v]][i];                qu.push(u);            }            else u = trie[fail[v]][i];        }    }}void mul(LL (*a)[maxn], LL (*b)[maxn]){    memset(m1, 0, sizeof mat0);    for(int i = 0; i < tt; i++)        for(int k = 0; k < tt; k++)            for(int j = 0; j < tt; j++)                m1[i][j] = (m1[i][j] + a[i][k] * b[k][j]) % mod;}void power(int n){    memset(m2, 0, sizeof mat0);    for(int i = 0; i < tt; i++)        m2[i][i] = 1;    while(n > 0)    {        if(n & 1) mul(m2, m0), swap(m2, m1);        mul(m0, m0), swap(m0, m1);        n >>= 1;    }}int main(){//  freopen("in.txt", "r", stdin);    id['A'] = 0, id['T'] = 1, id['C'] = 2, id['G'] = 3;    memset(trie, -1, sizeof trie);    memset(fail, -1, sizeof fail);    scanf("%d %d", &m, &n);    for(int i = 0; i < m; i++)    {        scanf(" %s", str);        ins(str, 0);    }    tt ++;    build_ac_automation(0);    for(int i = 0; i < tt; i++)        for(int j = 0; j < kind; j++)            if(!du[i] && !du[trie[i][j]]){                mat0[i][trie[i][j]] ++;            }    m0 = mat0;    m1 = mat1;    m2 = mat2;    power(n);    int res = 0;    for(int i = 0; i < tt; i++)        res += m2[0][i];    res %= mod;    cout << res << endl;    return 0;}
原创粉丝点击