Link:http://poj.org/problem?id=2778
字典樹的每個節點作爲一個狀態,矩陣記錄i點走一步的可行的狀態轉移的方法數,用矩陣快速冪計算所有可行的方法數。
//#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int mod = 100000;
const int N = 15;
const int M = 4;
const int root = 0;
//char to[5] = {"ACTG"};
int change(char c){
if(c == 'A')
return 0;
if(c == 'C')
return 1;
if(c == 'T')
return 2;
if(c == 'G')
return 3;
}
struct Ma{
LL p[N*N][N*N];
int Size;
void init(int _n){
Size = _n;
for(int i = 0; i < Size; i++)
for(int j = 0; j < Size; j++)
p[i][j] = 0;
}
};
struct Aho
{
struct Node{
int nex[M];
int fail,endd;
}node[N*N];
int Size;
queue<int> que;
int newnode(){
for(int i = 0; i < M; i++)
node[Size].nex[i] = 0;
node[Size].fail = node[Size].endd = 0;
return Size++;
}
void init(){
while(que.size()) que.pop();
Size = root;
newnode();
}
void Insert(char *s)
{
int L = strlen(s);
int now = root;
for(int i = 0; i < L; i++){
int x = change(s[i]);
if(node[now].nex[x]==0)
node[now].nex[x]=newnode();
now = node[now].nex[x];
}
node[now].endd = 1;
}
void build()
{
node[root].fail = root;
for(int i = 0; i < M; i++)
{
if(node[root].nex[i])
{
node[node[root].nex[i]].fail = root;
que.push(node[root].nex[i]);
}
}
while(que.size())
{
int u = que.front();
if(node[node[u].fail].endd) //當u的後綴是病毒,u也不能出現.
node[u].endd = 1;
que.pop();
for(int i = 0; i < M; i++)
{
if(node[u].nex[i]==0)
node[u].nex[i] = node[node[u].fail].nex[i];
else
{
node[node[u].nex[i]].fail = node[node[u].fail].nex[i];
que.push(node[u].nex[i]);
}
}
}
// for(int i = 0; i < Size; i++)
// printf("[%d %d %d]\n",i,node[i].fail,node[i].endd);
}
Ma getMa()
{
Ma mat;
mat.init(Size);
for(int i = root; i < Size; i++){
for(int j = 0; j < M; j++){
if(!node[i].endd && !node[node[i].nex[j]].endd)
mat.p[i][node[i].nex[j]] ++;
}
}
return mat;
}
}aho;
Ma Ma_mult(Ma a,Ma b)
{
Ma c;
c.init(a.Size);
for(int i = 0; i < a.Size; i++){
for(int j = 0; j < a.Size; j++){
for(int k = 0; k < a.Size; k++)
c.p[i][j] += a.p[i][k]*b.p[k][j];
c.p[i][j] %= mod;
}
}
return c;
}
Ma quick_mi(Ma a,int n)
{
Ma c;
c.init(a.Size);
for(int i = 0; i < c.Size; i++)
c.p[i][i] = 1;
while(n)
{
if(n&1) c = Ma_mult(c,a);
a = Ma_mult(a,a);
n >>= 1;
}
return c;
}
char s[N];
int main()
{
int m,n;
while(~scanf("%d %d",&m,&n))
{
aho.init();
for(int i = 0; i < m; i++)
{
scanf("%s",s);
aho.Insert(s);
}
aho.build();
Ma mat = aho.getMa();
// for(int i = 0; i < mat.Size; i++)
// {
// for(int j = 0; j < mat.Size; j++)
// printf("%lld ",mat.p[i][j]);
// puts("");
// }
mat = quick_mi(mat,n);
LL ans = 0;
for(int i = 0; i < mat.Size; i++)
ans += mat.p[0][i];
printf("%lld\n",ans%mod);
}
return 0;
}