Description
Input
Output
Sample Input
4 3 AT AC AG AA
Sample Output
36
思路:直接用AC自动机预处理出失败指针转移态,然后根据失败指针的转移态建立递推矩阵,外加个快速幂轻松搞定。
mod很占时间能不mod尽量少mod
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #define FOR(i,a,b) for(int i=a;i<=b;++i) #define clr(f,z) memset(f,z,sizeof(f)) #define LL unsigned long long using namespace std; const int msize=510; const int sig=4; const int mod=100000; class Matrix { public: LL f[140][140]; int n; Matrix(); Matrix(int x) { n=x; FOR(i,0,x-1)FOR(j,0,x-1)f[i][j]=0; } Matrix operator*(const Matrix&b)const { Matrix c=Matrix(n); FOR(i,0,n-1)FOR(j,0,n-1){FOR(k,0,n-1) c.f[i][j]+=f[i][k]*b.f[k][j]; c.f[i][j]%=mod; } return c; } }; class AC_Machine { public:int f[msize],ch[msize][sig],sz; bool val[msize]; void clear() { sz=1;clr(ch[0],0);val[0]=0; } int idx(char x) { if(x=='A')return 0; if(x=='G')return 1; if(x=='C')return 2; if(x=='T')return 3; } void insert(char*s) { int u=0,v,c; for(int i=0;s[i];++i) { c=idx(s[i]); if(!ch[u][c]) { clr(ch[sz],0);val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=1; } void getFail() { int u=0,v,r; queue<int>Q; FOR(c,0,sig-1) { u=ch[0][c]; if(u) { f[u]=0;Q.push(u); } } while(!Q.empty()) { r=Q.front();Q.pop(); val[r]|=val[ f[r] ]; FOR(c,0,sig-1) { u=ch[r][c]; if(!u) { ch[r][c]=ch[ f[r] ][c];continue; } v=f[r];Q.push(u); while(v&&!ch[v][c])v=f[v]; f[u]=ch[v][c]; } } } Matrix getMatrix() { Matrix ret=Matrix(sz); FOR(i,0,sz-1) FOR(j,0,3) if(!val[ch[i][j]]) { ret.f[i][ ch[i][j] ]++; } return ret; } }; Matrix M_pow(Matrix a,int m) { Matrix ret=Matrix(a.n); FOR(i,0,a.n-1)ret.f[i][i]=1; while(m) { if(m&1)ret=ret*a; a=a*a; m>>=1; } return ret; } AC_Machine ac; char s[55]; int n,m; int main() { while(~scanf("%d%d",&n,&m)) { ac.clear(); FOR(i,1,n) { scanf("%s",s); ac.insert(s); } ac.getFail(); Matrix ret=ac.getMatrix(); ret=M_pow(ret,m); LL ans=0; FOR(i,0,ac.sz-1) ans+=ret.f[0][i]; ans%=mod; printf("%lld\n",ans); } }