DNA Sequence
这题搞了我几个小时。先睡了,回头补博客。
题意:传送门
AC自动机学习博客:传送门
矩阵快速幂学习:队友wqqq的模板
AC自动机模板:bin巨板子胡改
矩阵快速幂模板:结合网友+小破站up
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define usll unsigned long long
const int mat_n=107;
const int MOD=100000;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
struct Matrix{
usll mat[mat_n][mat_n];
int n;
Matrix(){}
Matrix(int _n){
n=_n;
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 k=0;k<n;k++)
for(int j=0;j<n;j++){
ret.mat[i][j]+=(mat[i][k]*b.mat[k][j])%MOD;
ret.mat[i][j]%=MOD;
}return ret;
}
usll pow_m(usll a,int n){
usll ret=1,tmp=a;
while(n){
if(n&1)ret*=tmp;
tmp*=tmp;
n>>=1;
}return ret;
}
Matrix pow_M(Matrix a,ll n){
Matrix ret=Matrix(a.n);
for(int i=0;i<a.n;i++) ret.mat[i][i]=1;
Matrix tmp=a;
while(n){
if(n&1)ret=ret*tmp;
tmp=tmp*tmp;
n>>=1;
}return ret;
}
};
int chg(char ch){
int rnt=3;
if(ch=='A') rnt=0;
else if(ch=='C') rnt=1;
else if(ch=='T') rnt=2;
return rnt;
}
const int Mn=1000*50+100;
const int ALTN=4;
struct Trie{
int nxt[Mn][ALTN+3];
int fail[Mn];
bool end[Mn];
int root,L;
int newnode(){
for(int i=0;i<ALTN;++i) nxt[L][i]=-1;
end[L++]=false;
return L-1;
}
void init(){
L=0;
root=newnode();
}
void insert(char buf[]){
int len=strlen(buf);
int now=root;
for(int i=0;i<len;++i){
if(nxt[now][chg(buf[i])]==-1)
nxt[now][chg(buf[i])]=newnode();
now=nxt[now][chg(buf[i])];
}
end[now]=true;
}
void build(){
queue<int> Q;
fail[root]=root;
for(int i=0;i<ALTN;++i)
if(nxt[root][i]==-1) nxt[root][i]=root;
else {
fail[nxt[root][i]]=root;
Q.push(nxt[root][i]);
}
while(!Q.empty()){
int now=Q.front();Q.pop();
if(end[fail[now]]) end[now]=true;
for(int i=0;i<ALTN;++i)
if(nxt[now][i]==-1)
nxt[now][i]=nxt[fail[now]][i];
else {
fail[nxt[now][i]]=nxt[fail[now]][i];
Q.push(nxt[now][i]);
}
}
}
Matrix query(ll k){
Matrix ret=Matrix(L);
for(int i=0;i<L;++i)for(int j=0;j<4;++j)if(!end[i]&&!end[nxt[i][j]]) ret.mat[i][nxt[i][j]]++;
ret=ret.pow_M(ret,k);
// for(int i=0;i<ret.n;++i){for(int j=0;j<ret.n;++j)printf("%llu ",ret.mat[i][j]);printf("\n");}
return ret;
}
};
Trie ac;
char buf[17];
int main(){
int n;ll m;scanf("%d%lld",&n,&m);
ac.init();
for(int i=0;i<n;++i){
scanf("%s",buf);
ac.insert(buf);
}
ac.build();
Matrix M=ac.query(m);
ll ans=0;for(int i=0;i<M.n;++i) ans=(ans+M.mat[0][i])%MOD;
printf("%lld\n",ans);
return 0;
}