题目链接: http://poj.org/problem?id=2778
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#define sf scanf
#define pf printf
//#define LOCAL
using namespace std;
typedef long long LL;
const int maxn = 111;
const LL mod = 100000;
struct Matrix{
LL C[maxn][maxn];
int n;
};
Matrix operator*(Matrix a,Matrix b){
Matrix ret;
memset(ret.C,0,sizeof(ret.C));
ret.n = a.n;
for(int i = 1;i <= a.n;++i){
for(int j = 1;j <= a.n;++j){
for(int k = 1;k <= a.n;++k){
ret.C[i][j] += a.C[i][k] * b.C[k][j];
ret.C[i][j] %= mod;
}
}
}
return ret;
}
Matrix operator^(Matrix a,int n){
Matrix ret;
ret.n = a.n;
for(int i = 1;i <= ret.n;++i){
for(int j = 1;j <= ret.n;++j){
ret.C[i][j] = (i == j);
}
}
while(n){
if(n & 1){
ret = ret * a;
n--;
}
a = a * a;
n >>= 1;
}
return ret;
}
namespace AcAutomation {
const int sigma_size = 4;
const int maxnode = 111;
struct AcTrie {
int ch[maxnode][sigma_size];
int value[maxnode];
int fail[maxn];
int sz;
void Init(){
sz = 1;
memset(ch[0],0,sizeof(ch[0]));
value[0] = 0;
fail[0] = -1;
}
int IDX(char c){
switch (c){
case 'A' : return 0;
case 'C' : return 1;
case 'G' : return 2;
case 'T' : return 3;
}
}
void Insert(char* s,int v){ //插入模式串
int cur = 0;
while(*s){
int idx = IDX(*s);
if(!ch[cur][idx]){
memset(ch[sz],0,sizeof(ch[sz]));
value[sz] = 0;
ch[cur][idx] = sz++;
}
cur = ch[cur][idx];
s++;
}
value[cur] = v;
}
void GetFail(){ //得到Fail指针
queue<int> Q;
int f,cur;
Q.push(0);
while( !Q.empty() ){
cur = Q.front();Q.pop();
for(int i = 0;i < sigma_size;++i){
if(ch[cur][i]){
f = fail[cur];
while(f != -1 && !ch[f][i]) f = fail[f];
fail[ch[cur][i]] = (f != -1) ? ch[f][i] : 0;
Q.push(ch[cur][i]);
value[ch[cur][i]] = value[ch[cur][i]] | value[fail[ch[cur][i]]] | value[cur];
}
}
}
}
void Search(int cur,Matrix& Met){ //构建矩阵
for(int i = 0;i < sigma_size;++i){
if(ch[cur][i] && !value[ch[cur][i]]){
Met.C[cur + 1][ch[cur][i] + 1]++;
Search(ch[cur][i],Met);
}
else if(!ch[cur][i]){
int f = fail[cur];
while( f != -1 && !ch[f][i] ) {f = fail[f];}
if(f != -1){
if(!value[ch[f][i]]) Met.C[cur + 1][ch[f][i] + 1]++;
}
else Met.C[cur + 1][1]++;
}
}
}
};
}
AcAutomation::AcTrie Trie;
int main() {
#ifdef LOCAL
freopen("read.txt","r",stdin);
#endif // LOCAL
int n,m;
char Trage_DNA[15];
while( ~sf("%d%d",&n,&m) ){
Trie.Init();
for(int i = 0;i < n;++i){
sf("%s",Trage_DNA);
Trie.Insert(Trage_DNA,1);
}
Trie.GetFail();
Matrix met;
memset(met.C,0,sizeof(met.C));
met.n = Trie.sz;
Trie.Search(0,met);
met = met ^ m;
LL ret = 0;
for(int i = 1;i <= met.n;++i) {ret += met.C[1][i];ret = ret % mod;}
pf("%lld\n",ret);
}
return 0;
}