poj_2778_DNA Sequence(AC自动机+矩阵)

题目链接:poj_2778_DNA Sequence

题意:

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

题解:

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

 1 #include<cstdio>
 2 #include<cstring>
 3 #define mst(a,b) memset(a,b,sizeof(a))
 4 #define F(i,a,b) for(int i=a;i<=b;i++)
 5 typedef long long ll;
 6 //-----------------------矩阵-------------------------
 7 const int mat_N=11*11+7,mo=1e5;//矩阵阶数,取膜
 8 int N;
 9 struct mat{
10     ll c[mat_N][mat_N];
11     void init(){mst(c,0);}
12     mat operator*(mat b){
13         mat M;M.init();
14         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;
15         return M;
16     }
17     mat operator+(mat b){
18         mat M;
19         F(i,0,N)F(j,0,N)M.c[i][j]=(c[i][j]+b.c[i][j])%mo;
20         return M;
21     }
22     mat operator^(ll k){
23         mat ans,M=(*this);ans.init();
24         F(i,0,N)ans.c[i][i]=1;
25         while(k){if(k&1)ans=ans*M;k>>=1,M=M*M;}
26         return ans;
27     }
28 }A;
29 //-----------------------AC自动机-----------------------
30 const int AC_N=11*11,tyn=4;//数量乘串长,类型数
31 struct AC_automation{
32     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
33     inline int getid(char x){
34         if(x=='A')return 0;
35         if(x=='T')return 1;
36         if(x=='G')return 2;
37         if(x=='C')return 3;
38     }
39     void nw(){cnt[++tot]=0;memset(tr[tot],-1,sizeof(tr[tot]));}
40     void init(){tot=-1,fail[0]=-1,nw();}
41     void insert(char *s,int x=0){
42         for(int len=strlen(s),i=0,w;i<len;x=tr[x][w],i++)
43             if(tr[x][w=getid(s[i])]==-1)nw(),tr[x][w]=tot;
44         cnt[x]++;//串尾标记
45     }
46     void build(int head=1,int tail=0){
47         for(Q[++tail]=0;head<=tail;){
48             for(int i=0,x=Q[head++],p=-1;i<tyn;i++)if(~tr[x][i]){
49                 if(x==0)fail[tr[0][i]]=0;
50                 else for(p=fail[x],fail[tr[x][i]]=0;~p;p=fail[p])
51                         if(~tr[p][i]){fail[tr[x][i]]=tr[p][i];break;}
52                 if(cnt[fail[tr[x][i]]])cnt[tr[x][i]]=1;
53                 Q[++tail]=tr[x][i];
54             }else if(x==0)tr[x][i]=0;
55             else tr[x][i]=tr[fail[x]][i];
56         }
57     }
58 }AC;
59 
60 void build_mat()
61 {
62     A.init();
63     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]]++;
64 }
65 
66 int main()
67 {
68     ll n,m,ans;char buf[30];
69     while(~scanf("%lld%lld",&n,&m))
70     {
71         AC.init();
72         F(i,1,n)scanf("%s",buf),AC.insert(buf);
73         AC.build(),N=AC.tot,build_mat(),A=A^m,ans=0;
74         F(i,0,AC.tot)ans+=A.c[0][i];
75         printf("%lld\n",ans%mo);
76     }
77     return 0;
78 }
View Code

 

posted @ 2016-07-27 13:16  bin_gege  阅读(129)  评论(0编辑  收藏  举报