/*
poj2778
congyu liu 2017-9-22

AC自动机+矩阵快速幂
详见http://blog.csdn.net/morgan_xww/article/details/7834801
感谢博主
先将不能包含的基因组单词跑一遍AC自动机建图,
接着,问题转化成,求从trie树根节点出发,
沿着树边或fail边走k次,能有多少条路径。
同时,由于这道题要求基因不能包含以上单词,意味着
不能走到单词的结尾点,或者某个点存在后缀链接指向
某个单词的结尾,所以构建邻接矩阵时要删除这些点的入边和出边。
接下来就是用邻接矩阵求经过k条边的两点之间的方案数,矩阵乘法+快速幂即可。

要加强对于AC自动机状态图的理解!
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
#define ll long long 
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define frr(i,a,b) for(int i=a;i>=b;i--)
#define ms(a,b) memset(a,b,sizeof(a))
#define scfd(a) scanf("%d",a)
#define scflf(a) scanf("%lf",a)
#define scfs(a) scanf("%s",a)
#define ptfd(a) printf("%d\n",a)
#define ptfs(a) printf("%s\n",a)
#define showd(a,b) printf(a"=%d\n",b)
#define showlf(a,b) printf(a"=%lf\n",b)
#define shows(a,b) printf(a"=%s\n",b)
#define mmcp(a,b) memcpy(a,b,sizeof(b))
// #define DEBUG
const int MAXN=105;
const int ARGS=4;
const ll MOD=100000;
int ch[MAXN][ARGS],f[MAXN],nd[MAXN],sz;
bool end[MAXN],last[MAXN];
int n,l;
char s[15];
struct Matrix{
    ll n[MAXN][MAXN];
    Matrix(){
        ms(n,0);
    }
    Matrix operator*(Matrix &a){
        Matrix ans;
        fr(i,0,sz-1)
            fr(j,0,sz-1)
                fr(k,0,sz-1)
                    ans.n[i][j]=(n[i][k]*a.n[k][j]+ans.n[i][j])%MOD;
        return ans;
    }
};
inline int idx(char x){
    switch(x){
        case 'A':
            return 0;
        case 'C':
            return 1;
        case 'T':
            return 2;
        case 'G':
            return 3;
    }
}
void push(char *s){
    int l=strlen(s),nnd=0;
    fr(i,0,l-1){
        int idxx=idx(s[i]);
        if(!ch[nnd][idxx])
            nd[sz]=idxx,ch[nnd][idxx]=sz++;
        nnd=ch[nnd][idxx];
    }
    last[nnd]=end[nnd]=true;
    
}
void aho_init(){
    queue<int>q;
    fr(i,0,ARGS-1)
        if(ch[0][i])
            q.push(ch[0][i]);
    while(!q.empty()){
        int nnd=q.front();q.pop();
        fr(i,0,ARGS-1){
            int faf=f[nnd];
            while(faf&&!ch[faf][i])faf=f[faf];
            if(!ch[nnd][i]){
                ch[nnd][i]=ch[faf][i];
                continue;
            }
            f[ch[nnd][i]]=ch[faf][i];
            if(end[ch[nnd][i]]||end[f[ch[nnd][i]]]||last[f[ch[nnd][i]]])
                last[ch[nnd][i]]=true;
            else 
                last[ch[nnd][i]]=false;
            q.push(ch[nnd][i]);
        }
    }
}
Matrix get_table(){
    Matrix ans;
    fr(i,0,sz-1){
        if(last[i])continue;
        fr(j,0,ARGS-1){
            if(last[ch[i][j]])continue;
            ans.n[i][ch[i][j]]++;
        }
    }
    return ans;
}
void init(){
    sz=1;
    ms(ch,0);
    ms(nd,0);
    ms(f,0);
    ms(end,false);
    ms(last,false);
}
void solve(){
   
   while(~scanf("%d%d",&n,&l)){
       init(); 
       fr(i,0,n-1){
           scfs(s);
           push(s);
       }
       aho_init();
       Matrix t=get_table();
       #ifdef DEBUG
            fr(i,0,sz-1){
                fr(j,0,sz-1)
                    cout<<t.n[i][j]<<" ";
                cout<<endl;
            }
       #endif   
       Matrix ans;
       if(l)
            ans=t,l--;
       int cnt=1;
       while(l){
            if(l%2)
                ans=ans*t;
            l/=2;
            t=t*t;
            cnt*=2;
       }
       ll tans=0;
       fr(i,0,sz-1)
            tans=(tans+ans.n[0][i])%MOD;
       cout<<tans<<endl;
   }

}
int main(){
    solve();
    return 0;
}
 posted on 2017-09-22 16:52  cylcy  阅读(117)  评论(0编辑  收藏  举报