#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <math.h>
#define mod 100000
#define LL long long
using namespace std;
const int M = 4;
const int N = 1e6+10;
struct Matrix{
int mat[110][110];
int n;
Matrix(){}
Matrix(int nn){
n = nn;
for(int i = 0; i < n; ++i){
for(int j = 0; j < n; ++j){
mat[i][j] = 0;
}
}
}
Matrix operator * (const Matrix& b)const{
Matrix ret = Matrix(n);
for(int i = 0; i < n; ++i){
for(int j = 0; j < n; ++j){
for(int k = 0; k < n; ++k){
int tmp = (LL)mat[i][k]*b.mat[k][j]%mod;
ret.mat[i][j]=(ret.mat[i][j]+tmp)%mod;
}
}
}
return ret;
}
};
struct Trie{
int next[N][M],fail[N];
bool end[N];
int root,L;
int getIndex(char ch){
switch(ch){
case 'A':
return 0;
case 'C':
return 1;
case 'G':
return 2;
case 'T':
return 3;
}
}
int newNode(){
for(int i = 0; i < M; ++i){
next[L][i] = -1;
}
end[L++] = false;
return L-1;
}
void init(){
L = 0;
root = newNode();
}
void insert(char buf[]){
int now = root;
for(int i = 0 ; buf[i]; ++i){
int x = getIndex(buf[i]);
if(next[now][x] == -1){
next[now][x] = newNode();
}
now = next[now][x];
}
end[now] = true;
}
void build(){
queue<int>Q;
for(int i = 0; i < M; ++i){
if(next[root][i] == -1){
next[root][i] = root;
}
else{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while(!Q.empty()){
int now = Q.front();
Q.pop();
if(end[fail[now]] == true)
end[now] = true;
for(int i = 0; i < M; ++i){
if(next[now][i] == -1){
next[now][i] = next[fail[now]][i];
}
else{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
//计算的是选择0个、1个、、、n个的总数目
// Matrix getMatrix(){
// Matrix res = Matrix(1+L);
// for(int i = 0; i < L; ++i){
// for(int j = 0; j < M; ++j)
// if(end[next[i][j]] == false)
// res.mat[i][next[i][j]]++;
// }
// for(int i = 0; i < L+1; ++i){
// res.mat[i][L] = 1;
// }
// return res;
// }
//计算选择n个的数目
Matrix getMatrix(){
Matrix res = Matrix(L);
for(int i = 0; i < L; ++i){
for(int j = 0; j < M; ++j)
if(end[next[i][j]] == false)
res.mat[i][next[i][j]]++;
}
return res;
}
};
Trie ac;
char buf[20];
Matrix pow_Matrix(Matrix a,int n){
Matrix ret = Matrix(a.n);
for(int i = 0; i < ret.n; ++i)
ret.mat[i][i] = 1;
while(n){
if(n&1){
ret = ret*a;
}
a = a*a;
n >>= 1;
}
return ret;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)){
ac.init();
for(int i = 0; i < n; ++i){
scanf("%s",buf);
ac.insert(buf);
}
ac.build();
Matrix a = ac.getMatrix();
a = pow_Matrix(a,m);
int ans = 0;
for(int i = 0; i < a.n; ++i){
ans =(ans+a.mat[0][i])%mod;
}
printf("%d\n",ans);
}
return 0;
}
POJ 2778 DNA SequenceAC自动机 矩阵快速幂
最新推荐文章于 2020-02-02 20:44:43 发布