poj 2778 DNA Sequence (ac自动机+矩阵快速幂优化dp)

来源:互联网 发布:直销软件 编辑:程序博客网 时间:2024/05/20 15:57

题目:http://poj.org/problem?id=2778

题意:给出N段DNA序列(仅由‘A’,'T','G','C'四种字符组成),求一段长为L的DNA序列不包含前面给出的任何DNA序列的方案数。


分析:将N个字符串建成ac自动机,然后把所有禁止走的位置标记出来,然后利用ac自动机建二维矩阵Matrix[][],Matrix[u][v]表示节点u走一步到节点v的路径数。然后利用矩阵快速幂求出方案数。

PS:这题就是ac自动机建图+hdu 5318。

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;typedef long long LL;const int maxn = 103;const int kd = 4;const LL mod = 100000 ;int Msz;struct Matrix{LL M[maxn][maxn];}U,P;Matrix Multi(const Matrix &a,const Matrix &b){Matrix ret;memset(ret.M,0,sizeof(ret.M));for(int i=0;i<Msz;i++)for(int j=0;j<Msz;j++){for(int k=0;k<Msz;k++)ret.M[i][j]+=a.M[i][k]*b.M[k][j];ret.M[i][j]%=mod;}return ret;}Matrix Pow(Matrix a,int n){Matrix ret=U;while(n){if(n&1)ret=Multi(ret,a);a=Multi(a,a);n>>=1;}return ret;}struct trie{int son[maxn][kd],fbd[maxn],fail[maxn];int cnt,root;int newnode(){fill(son[cnt],son[cnt]+kd,-1);fbd[cnt]=0;return cnt++;}void Init(){cnt=0;root=newnode();}inline int idx(char ch){switch(ch){case 'A' : return 0;case 'C' : return 1;case 'G' : return 2;case 'T' : return 3;}return -1;}void Insert(char str[]){int index,i,now=root;for(i=0;str[i];i++){index=idx(str[i]);if(son[now][index]==-1)son[now][index]=newnode();now=son[now][index];}fbd[now]=1;}void findfail(){queue <int > q;int temp,i;for(i=0;i<kd;i++)if(son[root][i]==-1)son[root][i]=root;else{fail[son[root][i]]=root;q.push(son[root][i]);}while(!q.empty()){temp=q.front();q.pop();fbd[temp]|=fbd[fail[temp]];for(i=0;i<kd;i++)if(son[temp][i]==-1)son[temp][i]=son[fail[temp]][i];else{fail[son[temp][i]]=son[fail[temp]][i];q.push(son[temp][i]);}}}void GetU(){for(int i=0;i<maxn;i++)U.M[i][i]=1;}int Next(int cur,int x){if(fbd[cur] || fbd[son[cur][x]])return -1;return son[cur][x];}void GetP(){Msz=cnt;memset(P.M,0,sizeof(P.M));for(int i=0;i<Msz;i++){for(int j=0;j<kd;j++){int temp=Next(i,j);if(temp==-1)continue ;++P.M[i][temp];}}}}ac;char ss[maxn];int main(){int n,m,i,j;LL N,ans;ac.GetU();while(scanf("%d%lld",&n,&N)!=EOF){ac.Init();while(n--){scanf("%s",ss);ac.Insert(ss);}ac.findfail();ac.GetP();ans=0;if(N==1){for(i=0;i<kd;i++)ans+=P.M[ac.root][i];}else{Matrix temp=Pow(P,N-1);int buf[maxn]={0};for(i=0;i<kd;i++){int temp=ac.Next(ac.root,i);if(temp==-1)continue ;buf[temp]++;}for(i=0;i<Msz;i++)for(j=0;j<Msz;j++)ans+=buf[j]*temp.M[j][i]%mod;}printf("%lld\n",ans%mod);}return 0;}


0 0