POJ 2778 DNA Sequence(AC自动机确定DFA转移图+矩阵快速幂)
来源:互联网 发布:java软件设计模式 编辑:程序博客网 时间:2024/04/28 09:19
这道题极好的展示了AC自动机在构造转移图DFA上的应用
DFA转移图就是展示状态的转移过程的图,DFA图构造出来后就可以用DP求出任何DNA长度下,任何状态的个数
本题用自动机求出DFA矩阵,那么有
| dp[n][0] dp[n][1] ... dp[n][m] |=|dp[1][0] dp[1][1] ... dp[1][m] | * DFA^(n-1) (m指状态总数)
DP边界矩阵|dp[1][0] dp[1][1] ... dp[1][m] | 也就是DFA的第一行,所以dp[n]矩阵就是DFA^n
可见用自动机求某类状态转移方程不仅思路简单,而且可以用矩阵快速幂加速状态转移,复杂度log N
我是通过这篇学会的http://hi.baidu.com/ccsu_010/item/7847a3c17f6fe2bc0d0a7b89 ,感谢
//Accepted796K360MSC++3171B#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int M = 110;const int mod = 100000;struct mat{ ll a[M][M]; mat() { memset(a,0,sizeof(a)); }};mat DFA;struct node{ node *son[4]; node *fail; bool flag; int id;}trie[M],*que[M],*root;int Index(char x){ switch(x) { case 'A' : return 0; case 'C' : return 1; case 'G' : return 2; case 'T' : return 3; }}struct AC{ int head,tail,sz; node *createnode() { trie[sz].flag=0; memset(trie[sz].son,0,sizeof(trie[sz].son)); trie[sz].fail=NULL; trie[sz].id=sz; return &trie[sz++]; } void ini() { head=tail=0; sz=0; root=createnode(); } void Insert(char str[]) { node *cur=root; for(int i=0;str[i];i++) { int val=Index(str[i]); if(cur->flag) break; // 如果当前插入的已经是危险片段那么就可以不用继续插入了(针对此题而言) //要继续插入也可以不过它的后面全要标记成危险片段if(cur->flag) cur->son[val]->flag=true; if(cur->son[val]==NULL) { cur->son[val]=createnode(); } cur=cur->son[val]; } cur->flag=true; } void acfun() { que[head++]=root; while(tail<head) { node *cur=que[tail++]; for(int i=0;i<4;i++) { if(cur->son[i]!=NULL) { if(cur==root) cur->son[i]->fail=root; else cur->son[i]->fail=cur->fail->son[i]; if(cur->son[i]->fail->flag) cur->son[i]->flag=true; //易遗漏 que[head++]=cur->son[i]; } else { if(cur==root) cur->son[i]=root; else cur->son[i]=cur->fail->son[i]; } } } }}ac;mat mul(mat m1,mat m2){ mat ans; for(int i=0;i<ac.sz;i++) for(int j=0;j<ac.sz;j++) if(m1.a[i][j]) for(int k=0;k<ac.sz;k++) { ans.a[i][k]=(ans.a[i][k]+m1.a[i][j]*m2.a[j][k])%mod; } return ans;}int quickmul(mat m,int n){ mat ans; for(int i=0;i<ac.sz;i++) ans.a[i][i]=1; while(n) { if(n&1) ans=mul(ans,m); m=mul(m,m); n>>=1; } ll sum=0; for(int i=0;i<ac.sz;i++) { sum+=ans.a[0][i]; } return sum%mod;}void ini(){ ac.ini(); memset(DFA.a,0,sizeof(DFA.a));}int main(){ int m,n; while(~scanf("%d%d",&m,&n)) { ini(); while(m--) { char tmp[15]; scanf("%s",tmp); ac.Insert(tmp); } ac.acfun(); for(int i=0;i<ac.sz;i++) { if(!trie[i].flag) { for(int j=0;j<4;j++){ if(!trie[i].son[j]->flag) DFA.a[i][trie[i].son[j]->id ]++; } } } printf("%d\n",quickmul(DFA,n)); }}
0 0
- POJ 2778 DNA Sequence(AC自动机确定DFA转移图+矩阵快速幂)
- 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 【ac自动机 + dp + 矩阵快速幂】
- POJ 2778 DNA Sequence【AC自动机+矩阵快速幂】
- [AC自动机+dp+矩阵快速幂] poj 2778 DNA Sequence
- POJ 2778DNA Sequence AC自动机 + 矩阵快速幂
- 【AC自动机+矩阵快速幂】 POJ 2778 DNA Sequence
- poj 2778 DNA Sequence AC自动机+矩阵快速幂
- poj 2778 DNA Sequence(AC自动机+矩阵快速幂)
- POJ 2778 DNA Sequence AC自动机+矩阵快速幂
- POJ 2778 DNA Sequence [AC自动机 + 矩阵快速幂]
- poj--2778DNA Sequence+AC自动机+矩阵快速幂
- Sumsets (poj 2229 简单dp)
- Android 中Activity,Window和View之间的关系
- 编译原理笔记(2)
- Java finally语句到底是在return之前还是之后执行?
- HDU 1251 统计难题 字典树
- POJ 2778 DNA Sequence(AC自动机确定DFA转移图+矩阵快速幂)
- Fedora15 默认OpenJDK与SunJDK互相切换
- OC总结
- C51知识点拾遗
- Mahout快速入门教程
- 黑马程序员--面向对象2(Java)
- windows下mysql忘记root密码后查看或修改密码的方法
- 6、SDWebImage的使用
- 7、iOS pch文件创建及使用