题意:
有m个模式串,然后给你一个长度n,问你n长度的DNA序列有多少种不包含这m个模式串
题解:
这题显然要用AC自动机,将模式串的AC自动机建好后,再构建矩阵,矩阵的含义是自动机中0~tot的节点走一步到0~tot的节点的方案数,然后要走n步,所以上一个矩阵快速幂就行了,在建AC自动机的时候要改变一下失败指针的指向,不存在的节点就指向当前节点的失败指针,这样就模拟了AC自动机的匹配过程,需要画图好好理解一下。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 ",ans%mo); 76 } 77 return 0; 78 }