POJ 2778 DNA Sequence [AC自动机 + 矩阵快速幂]
2015-05-07 14:24
423 查看
http://poj.org/problem?id=2778
题意:给一些只由ACGT组成的模式串,问有多少种长度为n且不含有给出的模式串的DNA序列。
自动机的状态转换可以看成一个有向图(有重边的),该问题就转换成了在图上从0(trie树的根节点)开始走n步而不经过模式串末尾结点的路径数(重边算不同的路径)。
有向图又可以用一个矩阵 M 表示出来,则 Mij 表示图中 i 到 j 结点一步可达的路径数。 Mn 表示图中两点任意两点 n 步可达的路径数。
如此,本题只需将 M 构造出来,再将 Mn 的第一行的和求出来就好了。要行走路径不经过模式串末尾点,也就是使那些顶点不可达,即它们对应的那些列都是0。 Mn 用矩阵快速幂可搞。
题意:给一些只由ACGT组成的模式串,问有多少种长度为n且不含有给出的模式串的DNA序列。
自动机的状态转换可以看成一个有向图(有重边的),该问题就转换成了在图上从0(trie树的根节点)开始走n步而不经过模式串末尾结点的路径数(重边算不同的路径)。
有向图又可以用一个矩阵 M 表示出来,则 Mij 表示图中 i 到 j 结点一步可达的路径数。 Mn 表示图中两点任意两点 n 步可达的路径数。
如此,本题只需将 M 构造出来,再将 Mn 的第一行的和求出来就好了。要行走路径不经过模式串末尾点,也就是使那些顶点不可达,即它们对应的那些列都是0。 Mn 用矩阵快速幂可搞。
#include<cassert> #include<algorithm> #include<cmath> #include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<set> #include<queue> #include<map> using namespace std; #define rep(i,f,t) for(int i = (f), _end = (t); i <= _end; ++i) #define dep(i,f,t) for(int i = (f), _end = (t); i >= _end; --i) #define clr(c,x) memset(c,x,sizeof(c)); #define debug(x) cout<<"debug "<<x<<endl; const int INF = 0x3f3f3f3f; typedef long long int64; inline int RD(){ int res; scanf("%d",&res); return res; } #define Rush for(int casn = RD(), cas = 1; cas <= casn; ++cas) //******************************************************************** typedef vector<int> Vec; typedef vector<Vec> Mat; const int mod = 100000; const int Len = 110; struct Trie{ int next[Len][4]; int fail[Len]; int end[Len]; int sz; void init(){ sz = 0; clr(next[0], 0); } int idx(char c){ if(c == 'A')return 0; if(c == 'C')return 1; if(c == 'T')return 2; return 3; } int newnode(){ ++sz; clr(next[sz], 0); fail[sz] = end[sz] = 0; return sz; } void insert(char *s){ int u = 0; while(*s){ int nid = idx(*s++); int &v = next[u][nid]; if(!v) v = newnode(); u = v; } end[u] = 1; } void build(){ queue<int> q; rep(c,0,3)if(next[0][c])q.push(next[0][c]); while(!q.empty()){ int u = q.front(); q.pop(); int fu = fail[u]; if(end[fu]) end[u] = 1; rep(c,0,3){ int &v = next[u][c]; if(v){ q.push(v); fail[v] = next[fu][c]; }else{ v = next[fu][c]; } } } } void make(Mat &m){ m.resize(sz+1); rep(i,0,sz)m[i].resize(sz+1); rep(u,0,sz)rep(c,0,3){ int v = next[u][c]; if(!end[v]) ++m[u][v]; } } }ac; char str[15]; Mat mul(const Mat &a,const Mat &b){ Mat m( a.size(), Vec(b[0].size()) ); rep(k,0,b.size()-1){ rep(i,0,a.size()-1){ if(!a[i][k])continue; rep(j,0,b[0].size()-1){ if(!b[k][j])continue; m[i][j] = (m[i][j] + 1LL*a[i][k] * b[k][j] % mod) % mod; } } } return m; } Mat pow(Mat m, int b){ Mat res(m.size(), Vec(m.size())); rep(i,0,res.size()-1) res[i][i] = 1; while(b){ if(b&1){ res = mul(res, m); } m = mul(m, m); b >>= 1; } return res; } int main(){ int mi,n; while(~scanf("%d%d",&mi,&n)){ ac.init(); rep(i,1,mi){ scanf("%s",str); ac.insert(str); } ac.build(); Mat m; ac.make(m); Mat res = pow(m,n); int ans = 0; rep(j,0,res[0].size()-1){ ans = (ans + res[0][j]) % mod; } printf("%d\n",ans); } return 0; }
相关文章推荐
- poj 2778 DNA Sequence 【ac自动机 + dp + 矩阵快速幂】
- POJ 2778 DNA Sequence [AC自动机 + 矩阵快速幂]
- poj 2778 DNA Sequence(AC自动机 + 矩阵快速幂)
- POJ 题目2778 DNA Sequence(AC自动机,矩阵快速幂)
- POJ 2778 - DNA Sequence (AC自动机 矩阵快速幂)
- POJ 2778 DNA Sequence (AC自动机 + 矩阵快速幂)
- POJ 2778 DNA Sequence [AC自动机 矩阵乘法]
- POJ - 2778_DNA Sequence_AC自动机&&矩阵快速幂
- poj -- 2778 DNA Sequence && hdu -- 2243 考研路茫茫——单词情结(AC自动机 + 矩阵)
- POJ 2778 DNA Sequence (AC自动机,矩阵乘法)
- poj 2778 DNA Sequence 【AC自动机 + 矩阵加速】
- POJ 2778 DNA Sequence(AC自动机 + 矩阵乘法)
- POJ 2778 DNA Sequence && AC自动机 矩阵 矩阵加速
- POJ2778 DNA sequence[自动AC机&矩阵快速幂]
- 【POJ2778】【AC自动机】【矩阵快速幂】17.2.9 T2 DNA Sequence 题解
- poj2778.DNA Sequence (Trie图 && 矩阵乘)
- POJ2778----AC自动机的变形+矩阵快速幂(AC自动机和矩阵快速幂必做题)
- AC自动机专题——G - DNA Sequence POJ - 2778 矩阵快速幂+AC自动机
- POJ 2778 DNA Sequence (AC自动机+矩阵加速,4级)
- POJ 2778 DNA Sequence (AC 自动机+矩阵)