给出至多10个字符串。。长度不超过10。。且字符串均由ATCG四个字母组成。
构造一个长度为L的串。使给出的字符串均不是它的字串。求方案数。
对给出的字符串构造AC自动机。然后在AC自动机上进行DP。。
对于ac自动机,每输入一个字符。其对应自动机上的结点也发生移动。
f[i][j]表示第i个字符之后位于自动机上第j个结点。
f[i][j]=k0*f[i-1][0]+k1*f[i-1][1]+k2*f[i-1][2]+......
由于L太大。构造矩阵后用矩阵快速幂求解。
(具体看这里 http://blog.henix.info/blog/poj-2778-aho-corasick-dp.html)
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #define rep(i,a,b) for(int i=a;i<b;++i) using namespace std; const int MAXN = 100; const int MAXC = 4; const int MOD = 100000; int N; typedef long long ll; struct Matrix{ int data[MAXN][MAXN]; Matrix(){ memset(data,0,sizeof(data)); } Matrix operator * (Matrix &b) { Matrix r; rep(i,0,N) rep(j,0,N) rep(k,0,N){ r.data[i][j]+=(1ll*data[i][k]*b.data[k][j])%MOD; r.data[i][j]%=MOD; } return r; } }; struct Tnode{ Tnode *ch[MAXC]; Tnode *f; bool flag; } *init; Tnode pool[MAXN]; int cnt; inline int lx(char c){ if (c=='A') return 0; if (c=='T') return 1; if (c=='C') return 2; if (c=='G') return 3; } void insert(char *s){ Tnode *now = init; while(*s){ int p = lx(*s++); if (!now->ch[p]) now->ch[p]=&pool[++cnt]; now = now->ch[p]; } now->flag=true; } void build(){ queue <Tnode*> q; q.push(init); while(!q.empty()){ Tnode *now = q.front(); q.pop(); rep(i,0,MAXC){ if (now->ch[i]){ Tnode *p=now->f; while(p && !p->ch[i]) p=p->f; now->ch[i]->f = p?p->ch[i]:init; q.push(now->ch[i]); } } } init->f=init; rep(i,0,MAXC) if (init->ch[i]) q.push(init->ch[i]); else init->ch[i]=init; while(!q.empty()){ Tnode *now = q.front(); if (now->f->flag) now->flag=true; q.pop(); rep(i,0,MAXC) if (now->ch[i]) q.push(now->ch[i]); else now->ch[i]=now->f->ch[i]; } } void show(int p){ cout << "Fail: " << pool[p].f-pool << endl; rep(i,0,MAXC) cout << pool[p].ch[i]-pool << " "; cout << endl; } Matrix callMatrix(){ N = cnt+1; Matrix R; rep(i,0,N){ if (pool[i].flag) continue; rep(p,0,MAXC) R.data[pool[i].ch[p]-pool][i]++; } return R; } Matrix pow(Matrix x,ll e){ Matrix r; rep(i,0,N) r.data[i][i]=1; for (;e;e>>=1,x=x*x) if (e&1) r=r*x; return r; } char s[20]; Matrix X; int main(){ freopen("in.txt","r",stdin); init = &pool[0]; memset(pool,0,sizeof(pool)); cnt=0; int M,L; scanf("%d%d\n",&M,&L); while(M--){ scanf("%s",s); insert(s); } build(); X = callMatrix(); X = pow(X,L); int ans=0; rep(i,0,N){ if (pool[i].flag) continue; ans+=X.data[i][0]; ans%=MOD; } cout << ans << endl; }