#include<iostream>
#include<queue>
#include<map>
#include<cmath>
using namespace std;
#define N 35
#define M 26
#define FF(i,n) for(int i=0;i<n;i++)
int tree[N][M];
int Node;
int fail[N];
bool isword[N];
int index[N];
void init(){
Node=0;
memset(tree[0],0,sizeof(tree[0]));
memset(isword,false,sizeof(isword));
}
void insert(char *p){
int root=0;
int len=strlen(p);
for(int i=0;i<len;i++){
int c=p[i]-'a';
if(!tree[root][c]){
tree[root][c]=++Node;
memset(tree[Node],0,sizeof(tree[Node]));
}
root=tree[root][c];
}
isword[root]=true;
}
void AC(){
queue<int> q;
for(int i=0;i<M;i++)
if(tree[0][i]){
fail[tree[0][i]]=0;
q.push(tree[0][i]);
}
while(!q.empty()){
int p=q.front();
q.pop();
for(int i=0;i<M;i++){
if(tree[p][i]){
int v=tree[p][i];
q.push(v);
fail[v]=tree[fail[p]][i];
isword[v]|=isword[fail[v]];
}
else
tree[p][i]=tree[fail[p]][i];
}
}
}
int len;
struct Matrix_Cal{
unsigned __int64 mat[N][N];
}e,Init,tp1,tp2;
Matrix_Cal operator+(Matrix_Cal a ,Matrix_Cal b){
Matrix_Cal c;
FF(i,len)FF(j,len)
c.mat[i][j]=a.mat[i][j]+b.mat[i][j];
return c;
}
Matrix_Cal operator*(Matrix_Cal a , Matrix_Cal b){
Matrix_Cal c;
int i,j,k;
FF(i,len)FF(j,len)
c.mat[i][j] = 0;
FF(i,len)FF(k,len) if(a.mat[i][k])FF(j,len) if(b.mat[k][j])
c.mat[i][j]=c.mat[i][j]+a.mat[i][k]*b.mat[k][j];
return c;
}
Matrix_Cal operator^(Matrix_Cal a , int b){
Matrix_Cal c=e, q=a;
for(;b;b>>=1){
if(b&1) c=c*q;
q=q*q;
}
return c;
}
Matrix_Cal Matrix_Sum(Matrix_Cal a ,int b){
int n=0,s[N];
int i;
Matrix_Cal tp1,tp2;
while(b>0){
s[n++]=b&1;
b>>=1;
}
tp1=tp2=a;
for(i=n-2;i>=0;i--){
tp1=tp1*(tp2+e);
tp2=tp2*tp2;
if(s[i]){
tp2=tp2*a;
tp1=tp1+tp2;
}
}
return tp1;
}
void creat(){
int ind=0;
int i,j;
memset(Init.mat,0,sizeof(Init.mat));
FF(i,N)FF(j,N) e.mat[i][j]=(i==j);
memset(index,0,sizeof(index));
for(i=0;i<=Node;i++)
if(!isword[i])
index[i]=ind++;
for(i=0;i<=Node;i++)
if(!isword[i])
for(j=0;j<M;j++)
if(!isword[tree[i][j]])
Init.mat[index[i]][index[tree[i][j]]]++;
}
int main(void){
int n;
int m;
char ch[10];
while(~scanf("%d%d",&n,&m)){
init();
for(int i=0;i<n;i++){
scanf("%s",ch);
insert(ch);
}
AC();
creat();
int i,j;
len=N;
tp1=Matrix_Sum(Init,m);
Init.mat[0][0]=26;
len=1;
tp2=Matrix_Sum(Init,m);
for(int i=0;i<N;i++)
tp2.mat[0][0]-=tp1.mat[0][i];
printf("%I64u\n",tp2.mat[0][0]);
}
}
AC自动机加矩阵
最新推荐文章于 2022-06-19 00:24:59 发布