首页 > 代码库 > 【POJ2778】AC自动机,DP,矩阵乘法
【POJ2778】AC自动机,DP,矩阵乘法
题意:给出n个字串表示“缺陷基因”,然后让求长度为m的基因(4^m个)中有多少个不带病。
题解:首先建立AC自动机,然后从每个节点开始选“ATGC”有四种往外转移的途径。
如:ACG,C这两个基因建一个ACauto,然后转移矩阵为下。
2 1 0 0 1
2 1 1 0 0
1 1 0 1 1
2 1 0 0 1
2 1 0 0 1
然后把危险状态删去(赋0),即基因结束节点的行和列。
然后矩阵变成
2 1 0 0 0
2 1 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
即
2 1
2 1
然后做矩阵乘法得出答案!
/*poj2778*/ #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 100 #define M 4 #define MOD 100000 using namespace std; int next[N][M],fail[N],map[N][N],crs[N],root,cnt,n,m; bool end[N],danger[N],visit[M]; char t[N]; queue<int>q; struct mrx { long long s[N][N]; }I,O; mrx mul(mrx a,mrx b) { int i,j,k; mrx c=I; for(i=0;i<=cnt;i++) { for(j=0;j<=cnt;j++) { for(k=0;k<=cnt;k++) { c.s[i][j]+=a.s[i][k]*b.s[k][j]; } c.s[i][j]%=MOD; } } return c; } mrx power(mrx a,int p) { mrx ans=O; while(p) { if(p&1) { ans=mul(ans,a); } a=mul(a,a); p>>=1; } return ans; } void init() { root=cnt=0; memset(fail,0,sizeof(fail)); memset(end,0,sizeof(end)); memset(map,0,sizeof(map)); while(!q.empty())q.pop(); } void acauto() { int i,j,u,v,temp,alp,flag; scanf("%d%d",&n,&m); crs['A']=0; crs['T']=1; crs['G']=2; crs['C']=3; for(i=1;i<=n;i++)/*insert*/ { scanf("%s",t+1); for(temp=root,j=1;t[j];j++) { alp=crs[t[j]]; if(!next[temp][alp])next[temp][alp]=++cnt; temp=next[temp][alp]; } end[temp]=1; } q.push(root);/*维护fail指针*/ while(!q.empty()) { u=q.front();q.pop(); for(i=0;i<M;i++) { v=next[u][i]; if(v) { if(end[v])danger[v]=1; if(u==root)fail[v]=root; else { temp=fail[u]; while(temp&&!next[temp][i])temp=fail[temp]; fail[v]=next[temp][i]; if(danger[fail[v]])danger[v]=1; } q.push(v); } } } for(i=0;i<=cnt;i++) { temp=i;flag=0; memset(visit,0,sizeof(visit)); while(temp&&flag<M) { for(j=0;j<M;j++)if(!visit[j]&&next[temp][j]) { map[i][next[temp][j]]++; visit[j]=1; flag++; } temp=fail[temp]; } if(flag<M)for(j=0;j<M;j++)if(!visit[j]) { map[i][next[0][j]]++; } } for(i=0;i<=cnt;i++)if(danger[i]) { for(j=0;j<=cnt;j++)map[i][j]=map[j][i]=0; } } void handle() { int i,j; mrx P=I; for(i=0;i<=cnt;i++)O.s[i][i]=1; for(j=0;j<=cnt;j++)for(i=0;i<=cnt;i++) { P.s[i][j]=map[j][i]; } P=mul(O,power(P,m)); long long ans=0; for(i=0;i<=cnt;i++) { ans+=P.s[i][0]; } cout<<ans%MOD<<endl; } int main() { // freopen("test.in","r",stdin); acauto(); handle(); return 0; }
【POJ2778】AC自动机,DP,矩阵乘法
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。