POJ 2778 DNA Sequence(AC自动机加矩阵快速幂)
关于矩阵的幂,参见:http://www.mynameisdhr.com/%e7%9f%a9%e9%98%b5%e7%9a%84%e5%b9%82/
题意是给你m个致病DNA序列,只包含四种字符ATCG,现在问你任意的长度为n的DNA序列当中有多少种不包含致病DNA序列的
首先建立AC自动机,考虑一些fail树上的性质,某个节点的fail边指向的是某个串的前缀与当前串后缀相同的位置
考虑邻接矩阵的性质,边权为1的无向图构建的允许重边的邻接矩阵的n次方是从i走到j的路径条数
构建邻接矩阵,以病毒串结尾的位置设为0,注意的是如果某个点的fail边指向病毒串结尾位置,这个点也要设为0
狗屎POJ不能用万能头
代码:
#include <cstring> #include <cstdio> #include <queue> //#define int long long using namespace std; typedef long long ll; const ll mod=100000; const int maxn=105; ll init[101][101]; int n,m; char s[maxn]; struct AC_AUTO{ int c[maxn*23][4],cnt,fl[maxn*23]; bool ed[maxn*23]; queue<int> q; int to(char c){ if(c=='A') return 0; else if(c=='C') return 1; else if(c=='G') return 2; else if(c=='T') return 3; } void ins(char *s){ int l=strlen(s),now=0; for(int i=0;i<l;++i){ if(!c[now][to(s[i])]) c[now][to(s[i])]=++cnt; now=c[now][to(s[i])]; } ed[now]=1; } void build(){ for(int i=0;i<=3;++i){ if(c[0][i]){ fl[c[0][i]]=0; q.push(c[0][i]); } } while(!q.empty()){ int f=q.front(); q.pop(); if(ed[fl[f]]) ed[f]=1;// for(int i=0;i<=3;++i){ if(c[f][i]){ fl[c[f][i]]=c[fl[f]][i]; q.push(c[f][i]); } else c[f][i]=c[fl[f]][i]; } } } }ac; void mul(ll x[101][101],ll y[101][101]) { ll tmp[101][101]; memset(tmp,0,sizeof(tmp)); for(int k=0;k<=ac.cnt;k++) for(int i=0;i<=ac.cnt;i++) for(int j=0;j<=ac.cnt;j++) tmp[i][j]=(tmp[i][j]+x[i][k]*y[k][j])%mod; for(int i=0;i<=ac.cnt;i++) for(int j=0;j<=ac.cnt;j++) x[i][j]=tmp[i][j]; } void qpow(int b){ ll ans[101][101]; memset(ans,0,sizeof(ans)); for(int i=0;i<=ac.cnt;++i) ans[i][i]=1; while(b){ if(b&1) mul(ans,init); mul(init,init); b>>=1; } for(int i=0;i<=ac.cnt;i++) for(int j=0;j<=ac.cnt;j++) init[i][j]=ans[i][j]; } ll query(){ memset(init,0,sizeof(init)); for(int i=0;i<=ac.cnt;++i){ if(ac.ed[i]) continue;// for(int j=0;j<=3;++j){ int nxt=ac.c[i][j]; if(!ac.ed[nxt]) init[i][nxt]++; } } qpow(m); ll res=0; for(int i=0;i<=100;++i){ res=(res+init[0][i])%mod; } return res; } signed main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%s",s); ac.ins(s); } ac.build(); printf("%lld",query()); return 0; }
浙公网安备 33010602011771号