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;}