您的位置:首页 > 产品设计 > UI/UE

poj_2778_DNA Sequence(AC自动机+矩阵)

2016-07-27 13:16 471 查看

题目链接:poj_2778_DNA Sequence

题意:

有m个模式串,然后给你一个长度n,问你n长度的DNA序列有多少种不包含这m个模式串

题解:

这题显然要用AC自动机,将模式串的AC自动机建好后,再构建矩阵,矩阵的含义是自动机中0~tot的节点走一步到0~tot的节点的方案数,然后要走n步,所以上一个矩阵快速幂就行了,在建AC自动机的时候要改变一下失败指针的指向,不存在的节点就指向当前节点的失败指针,这样就模拟了AC自动机的匹配过程,需要画图好好理解一下。

#include<cstdio>
#include<cstring>
#define mst(a,b) memset(a,b,sizeof(a))
#define F(i,a,b) for(int i=a;i<=b;i++)
typedef long long ll;
//-----------------------矩阵-------------------------
const int mat_N=11*11+7,mo=1e5;//矩阵阶数,取膜
int N;
struct mat{
ll c[mat_N][mat_N];
void init(){mst(c,0);}
mat operator*(mat b){
mat M;M.init();
F(i,0,N)F(j,0,N)F(k,0,N)M.c[i][j]=(M.c[i][j]+c[i][k]*b.c[k][j])%mo;
return M;
}
mat operator+(mat b){
mat M;
F(i,0,N)F(j,0,N)M.c[i][j]=(c[i][j]+b.c[i][j])%mo;
return M;
}
mat operator^(ll k){
mat ans,M=(*this);ans.init();
F(i,0,N)ans.c[i][i]=1;
while(k){if(k&1)ans=ans*M;k>>=1,M=M*M;}
return ans;
}
}A;
//-----------------------AC自动机-----------------------
const int AC_N=11*11,tyn=4;//数量乘串长,类型数
struct AC_automation{
int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
inline int getid(char x){
if(x=='A')return 0;
if(x=='T')return 1;
if(x=='G')return 2;
if(x=='C')return 3;
}
void nw(){cnt[++tot]=0;memset(tr[tot],-1,sizeof(tr[tot]));}
void init(){tot=-1,fail[0]=-1,nw();}
void insert(char *s,int x=0){
for(int len=strlen(s),i=0,w;i<len;x=tr[x][w],i++)
if(tr[x][w=getid(s[i])]==-1)nw(),tr[x][w]=tot;
cnt[x]++;//串尾标记
}
void build(int head=1,int tail=0){
for(Q[++tail]=0;head<=tail;){
for(int i=0,x=Q[head++],p=-1;i<tyn;i++)if(~tr[x][i]){
if(x==0)fail[tr[0][i]]=0;
else for(p=fail[x],fail[tr[x][i]]=0;~p;p=fail

) if(~tr[p][i]){fail[tr[x][i]]=tr[p][i];break;} if(cnt[fail[tr[x][i]]])cnt[tr[x][i]]=1; Q[++tail]=tr[x][i]; }else if(x==0)tr[x][i]=0; else tr[x][i]=tr[fail[x]][i]; } } }AC; void build_mat() { A.init(); F(i,0,AC.tot)F(j,0,3)if(!AC.cnt[i]&&!AC.cnt[AC.tr[i][j]])A.c[i][AC.tr[i][j]]++; } int main() { ll n,m,ans;char buf[30]; while(~scanf("%lld%lld",&n,&m)) { AC.init(); F(i,1,n)scanf("%s",buf),AC.insert(buf); AC.build(),N=AC.tot,build_mat(),A=A^m,ans=0; F(i,0,AC.tot)ans+=A.c[0][i]; printf("%lld\n",ans%mo); } return 0; }

View Code [p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: