POJ 2778 DNA Sequence(AC自动机+矩阵)
来源:互联网 发布:真小人 伪君子知乎 编辑:程序博客网 时间:2024/05/22 05:06
转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526 by---cxlove
题目:长度为N的DNA串不包含模式串的有多少个。
http://poj.org/problem?id=2778
N为20000000000,如此大的规模,肯定是lg(N)的算法,就会想到矩阵。
长度为10的模式串,10个,而且只有4个字母,最多不超过100个状态
建立AC自动机,记录里面的转移。
和基本的AC自动机有一点点不一样,如果某个结点的某个孩子结点为空,其它它还是可以转移的。
也就是他是可以存在后继状态,如果这个结点为根,那么还是转移到根,否则就转向失败指针指向的孩子结点。
需要建立转移矩阵,使用静态Trie,便于建立矩阵,两个状态之间可以转移,相当于存在一条路径,最终要求的是从空开始路径长度为n的个数。
不知道为什么,把Trie删掉反而会RE。
另外会超int,需要用64位整数。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define N 100005#define MOD 100000#define LL long longusing namespace std;struct Trie{ Trie *next[4]; Trie *fail; int kind,isword;};Trie *que[N],s[N];int idx;int id(char ch){ if(ch=='A') return 0; else if(ch=='T') return 1; else if(ch=='C') return 2; return 3;}Trie *NewTrie(){ //静态Trie Trie *tmp=&s[idx]; for(int i=0;i<4;i++) tmp->next[i]=NULL; tmp->isword=0; tmp->fail=NULL; tmp->kind=idx++; return tmp;}void Insert(Trie *root,char *s,int len){ Trie *tmp=root; for(int i=0;i<len;i++){ if(tmp->next[id(s[i])]==NULL) tmp->next[id(s[i])]=NewTrie(); tmp=tmp->next[id(s[i])]; } tmp->isword=1;}void Bulid_fail(Trie *root){ int tail=0,head=0; que[tail++]=root; root->fail=NULL; while(head<tail){ Trie *tmp=que[head++]; for(int i=0;i<4;i++){ if(tmp->next[i]==NULL){ if(tmp==root) tmp->next[i]=root; else tmp->next[i]=tmp->fail->next[i]; } else{ if(tmp==root) tmp->next[i]->fail=root; else{ tmp->next[i]->fail=tmp->fail->next[i]; if(tmp->next[i]->fail->isword) tmp->next[i]->isword=1; } que[tail++]=tmp->next[i]; } } }}char str[15];struct Matrix{ LL m[101][101];}Init;Matrix mult(Matrix m1,Matrix m2){ Matrix ans; memset(ans.m,0,sizeof(ans.m)); for(int i=0;i<idx;i++){ for(int k=0;k<idx;k++){ if(m1.m[i][k]==0) continue; for(int j=0;j<idx;j++){ ans.m[i][j]+=(LL)m1.m[i][k]*m2.m[k][j]; if(ans.m[i][j]>=MOD) ans.m[i][j]%=MOD; } } } return ans;}Matrix PowMod(Matrix m1,int n){ Matrix ans; for(int i=0;i<idx;i++) for(int j=0;j<idx;j++) ans.m[i][j]=i==j; while(n){ if(n&1) ans=mult(ans,m1); m1=mult(m1,m1); n>>=1; } return ans;}int main(){ int m,n; while(scanf("%d%d",&m,&n)!=EOF){ idx=0; Trie *root=NewTrie(); for(int i=0;i<m;i++){ scanf("%s",str); Insert(root,str,strlen(str)); } Bulid_fail(root); memset(Init.m,0,sizeof(Init.m)); for(int i=0;i<idx;i++){ for(int j=0;j<4;j++){ Trie *son=s[i].next[j]; if(!son->isword&&!s[i].isword) Init.m[i][son->kind]++; } } Init=PowMod(Init,n); LL ans=0; for(int i=0;i<idx;i++){ ans+=Init.m[0][i]; if(ans>=MOD) ans-=MOD; } printf("%I64d\n",ans); } return 0;}
- 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自动机 矩阵加速DP
- POJ 2778 DNA Sequence【AC自动机+矩阵快速幂】
- poj 2778 DNA Sequence(AC自动机+矩阵快速幂)
- POJ 2778 DNA Sequence(AC自动机+矩阵幂DP)
- [AC自动机+dp+矩阵快速幂] poj 2778 DNA Sequence
- POJ 2778 DNA Sequence AC自动机+DP+矩阵二分加速
- POJ 2778 - DNA Sequence (AC自动机 矩阵快速幂)
- POJ 2778DNA Sequence AC自动机 + 矩阵快速幂
- 【AC自动机+矩阵快速幂】 POJ 2778 DNA Sequence
- poj 2778 DNA Sequence AC自动机+矩阵快速幂
- 如何通过命令查看CentOS版本号
- 全排列
- 1029. Rabbit
- 递增单链表删除所有大于mink且小于maxK的元素。
- 关于gridview如何添加编辑删除
- POJ 2778 DNA Sequence(AC自动机+矩阵)
- SED单行脚本快速参考
- Google Map api key
- hdu 1220
- poj 2985 并查集+线段树 线段树求第k大数 The k-th Largest Group
- vc++学习笔记10
- GPU--图形处理器
- MyEclipse连接MySQL的方法
- Oracle中的pfile和spfile详解