POJ 2778 DNA Sequence ( Trie图矩阵快速幂 )
Posted shuaihui520
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2778 DNA Sequence ( Trie图矩阵快速幂 )相关的知识,希望对你有一定的参考价值。
题意 : 给出一些病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个
分析:
我们先分析Tire 图的结构 : Trie图是在AC自动机的原型上增添边使得状态可以快速转移,标记危险的节点(后缀是不良单词的节点); 那我们是想构造长度是n不包含不良串对不对 , 那是不是在trie图上从0节点走n步到安全节点的方案数(Trie图也是状态转移图)
在一个有向图中,A走k步到B的方案数(这显然是经典的矩阵快速幂问题),(原理需要自己搜索)先对原图建立一个邻接表M[i][j] , M[i][j] =1表示i到j有边直接相连,然后ans=pow(M,k) ,ans[A][B] 为答案
#include<queue> #include<stdio.h> #include<string.h> using namespace std; const int Max_Tot = 1e2 + 10; const int Letter = 4; const int MOD = 1e5; int maxn; int mp[128]; struct mat int m[111][111]; unit, M; mat operator * (mat a, mat b) mat ret; long long x; for(int i=0; i<maxn; i++) for(int j=0; j<maxn; j++) x = 0; for(int k=0; k<maxn; k++) x += (long long)a.m[i][k]*b.m[k][j]; ret.m[i][j] = x % MOD; return ret; inline void init_unit() for(int i=0; i<maxn; i++) unit.m[i][i] = 1; mat pow_mat(mat a, int n) mat ret = unit; while(n) if(n&1) ret = ret * a; a = a*a; n >>= 1; return ret; struct Aho struct StateTable int Next[Letter]; int fail, flag; Node[Max_Tot]; int Size; queue<int> que; inline void init() while(!que.empty()) que.pop(); memset(Node[0].Next, 0, sizeof(Node[0].Next)); Node[0].fail = Node[0].flag = 0; Size = 1; inline void insert(char *s) int now = 0; for(int i=0; s[i]; i++) int idx = mp[s[i]]; if(!Node[now].Next[idx]) memset(Node[Size].Next, 0, sizeof(Node[Size].Next)); Node[Size].fail = Node[Size].flag = 0; Node[now].Next[idx] = Size++; now = Node[now].Next[idx]; Node[now].flag = 1; //1) 如果son[i]不存在,将它指向 当前结点now的fail指针指 //向结点的i号后继(保证一定已经计算出来)。 //2) 如果son[i]存在,将它的fail指针指向 当前结点now的fail //指针指向结点的i号后继(保证一定已经计算出来)。 inline void BuildFail() Node[0].fail = 0; for(int i=0; i<Letter; i++) if(Node[0].Next[i]) Node[Node[0].Next[i]].fail = 0; que.push(Node[0].Next[i]); else Node[0].Next[i] = 0;///必定指向根节点 while(!que.empty()) int top = que.front(); que.pop(); if(Node[Node[top].fail].flag) Node[top].flag = 1; for(int i=0; i<Letter; i++) int &v = Node[top].Next[i]; if(v) que.push(v); Node[v].fail = Node[Node[top].fail].Next[i]; else v = Node[Node[top].fail].Next[i]; inline void BuildMatrix() for(int i=0; i<Size; i++) for(int j=0; j<Size; j++) M.m[i][j] = 0; for(int i=0; i<Size; i++) for(int j=0; j<Letter; j++) if(!Node[i].flag && !Node[ Node[i].Next[j] ].flag) M.m[i][Node[i].Next[j]]++; maxn = Size; ac; char S[11]; int main(void) mp[‘A‘]=0, mp[‘T‘]=1, mp[‘G‘]=2, mp[‘C‘]=3; int n, m; while(~scanf("%d %d", &m, &n)) ac.init(); for(int i=0; i<m; i++) scanf("%s", S); ac.insert(S); ac.BuildFail(); ac.BuildMatrix(); // for(int i=0; i<10; i++) // for(int j=0; j<10; j++) // printf("%d ", M.m[i][j]); // puts(""); // puts(""); init_unit(); M = pow_mat(M, n); // for(int i=0; i<10; i++) // for(int j=0; j<10; j++) // printf("%d ", M.m[i][j]); // puts(""); // puts(""); int ans = 0; for(int i=0; i<ac.Size; i++) ans += M.m[0][i]; ans %= MOD; printf("%d\n", ans); return 0;
以上是关于POJ 2778 DNA Sequence ( Trie图矩阵快速幂 )的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2778 DNA Sequence (矩阵快速幂 + AC自动鸡)
poj 2778 DNA Sequence ac自动机+矩阵快速幂