Poj 2778 DNA Sequence (AC自动机+矩阵)
来源:互联网 发布:整站优化seo 上海 编辑:程序博客网 时间:2024/05/01 15:37
题目大意:
给出N个串,问在长度为L的所有串中,不包含任一已知串的个数有多少个。
思路分析:
已知一个矩阵A,A[i][j] 表示 节点i 到 节点 j 有一条变可以到达的方法数。
那么A^2 ,这个矩阵的 [i][j] 就代表这个节点 i 到节点 j 有两条边可以到达的方法数。
那么知道这个结论,我们要做的就是求一个节点到另外一个节点,要经过L条变(对应这长度为L的单词),而又要满足任意一条边都不能经过已知单词。
所以我们要用到ac自动机处理出所有已知的单词,在ac自动机上得到这个矩阵,使得任意两个节点之间都不是已知单词的结尾,我们才连一条边。
还要理解AC自动机的一点,就是在失配的时候,也就是要得到fail的时候,其实可以抽象成你fail的下一个节点就是这个节点的next节点。可以看成是一个单词。
那么也就要加上代码中标记上的那个注释上的判断。可以稍微想一想。
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <queue>#define N 105#define maxn 10005using namespace std;typedef long long ll;const int mod = 100000;int rev[180];const char tab = 0;const int max_next = 4;int next[maxn][max_next],fail[maxn],num[maxn],siz;int newnode(){ for(int i=0;i<max_next;i++) next[siz][i]=0; fail[siz]=num[siz]=0; return siz++;}void init(){ siz=0; newnode();}void Insert(char *s,int len){ int p=0; for(int i=0;i<len;i++) { int &x=next[p][rev[s[i]]]; p=x?x:x=newnode(); } num[p]++;}void acbuild(){ queue<int>Q; Q.push(0); while(!Q.empty()) { int temp=Q.front(); Q.pop(); for(int i=0;i<max_next;i++) { int v=next[temp][i]; if(v==0)next[temp][i]=next[fail[temp]][i]; else Q.push(v); if(temp!=0)fail[v]=next[fail[temp]][i]; if(num[next[fail[temp]][i]])num[next[temp][i]]++;//--------- } }}struct matrix{ int r,c; ll data[N][N]; matrix(){} matrix(int _r,int _c):r(_r),c(_c){} friend matrix operator * (const matrix A,const matrix B) { matrix res; res.r=A.r;res.c=B.c; memset(res.data,0,sizeof res.data); for(int i=0;i<A.r;i++) { for(int j=0;j<B.c;j++) { for(int k=0;k<A.c;k++) { if(A.data[i][k] && B.data[k][j]){ res.data[i][j]+=A.data[i][k]*B.data[k][j]; res.data[i][j]%=mod; } } } } return res; } friend matrix operator + (const matrix A,const matrix B) { matrix res; res.r=A.r;res.c=A.c; memset(res.data,0,sizeof res.data); for(int i=0;i<A.r;i++) { for(int j=0;j<A.c;j++) { res.data[i][j]=A.data[i][j]+B.data[i][j]; res.data[i][j]%=mod; } } return res; } friend matrix operator - (const matrix A,const matrix B) { matrix res; res.r=A.r;res.c=A.c; memset(res.data,0,sizeof res.data); for(int i=0;i<A.r;i++) { for(int j=0;j<A.c;j++) { res.data[i][j]=A.data[i][j]-B.data[i][j]; res.data[i][j]=(res.data[i][j]%mod+mod)%mod; } } return res; } friend matrix operator ^ (matrix A,int n) { matrix res; res.r=A.r;res.c=A.c; memset(res.data,0,sizeof res.data); for(int i=0;i<A.r;i++)res.data[i][i]=1; while(n) { if(n&1)res=res*A; A=A*A; n>>=1; } return res; } void print() { for(int i=0;i<r;i++) { for(int j=0;j<c;j++) printf("%d ",data[i][j]); puts(""); } }}E,zero;char word[10005];int main(){ for(int i=0;i<N;i++) E.data[i][i]=1; rev['A']=0; rev['C']=1; rev['G']=2; rev['T']=3; int n,L; while(scanf("%d%d",&n,&L)!=EOF) { init(); for(int i=1;i<=n;i++) { scanf("%s",word); Insert(word,strlen(word)); } acbuild(); matrix origin(siz,siz); for(int i=0;i<siz;i++) { if(!num[i]) { for(int d=0;d<4;d++) { if(!num[next[i][d]]) { origin.data[i][next[i][d]]++; } } } } origin= origin^L; int ans=0; for(int i=0;i<siz;i++) { if(!num[i]) ans=(ans+origin.data[0][i])%mod; } printf("%d\n",ans); } return 0;}
0 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自动机+矩阵快速幂
- cookie ,session 和localStorage的区别详解
- 谈谈boost.asio的异步发送
- vector 二维数组 初始化
- 【Spring】MVC
- Android 反编译apk 到java源码的方法
- Poj 2778 DNA Sequence (AC自动机+矩阵)
- MySQL联合查询语法内联、左联、右联、全联
- chapter4 运算符及其优先级
- .net,C#,Ftp各种操作,上传,下载,删除文件,创建目录,删除目录,获得文件列表等
- jquery 判断元素下是不是有子元素
- WordPress主题导航菜单制作的几种方法(二)
- 嵌入式启动之四:S5PV210 IROM BL0启动
- 链表中倒数第k个结点
- ios将银行卡号格式化