#include <cstdio>
#include <queue>
#include <cstring>
using namespace std; const int mo=; int cnt; int trie[][];
int val[];
int f[],last[];
int n,m;
char st[][];
int tmp[];
int dp[][][]; int newnode(){
return(++cnt);
} void ins(int a[],int len){
int t=;
for (int i=;i<=len;i++){
if (trie[t][a[i]]==) t=trie[t][a[i]]=newnode();else
t=trie[t][a[i]];
}
val[t]=;
} queue <int> q;
void getfail(){
for (int i=;i<=;i++)
if (trie[][i]){
q.push(trie[][i]);
f[trie[][i]]=last[trie[][i]]=;
} while (!q.empty()){
int t=q.front();q.pop();
for (int i=;i<=;i++){
int u=trie[t][i];
if (u==) {trie[t][i]=trie[f[t]][i];continue;}
q.push(u);
f[u]=trie[f[t]][i];
if (val[f[u]]) last[u]=f[u]/*,val[u]=1*/;else last[u]=last[f[u]];
}
}
} int main(){
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++){
scanf("%s",&st[i]);
int le=strlen(st[i]);
for (int j=;j<=le;j++) tmp[j]=st[i][j-]-'A'+;
ins(tmp,le);
} getfail(); dp[][][]=;
for (int i=;i<m;i++)
for (int j=;j<=cnt;j++){
if (dp[i][j][]){
for (int k=;k<=;k++)
if (val[trie[j][k]])
dp[i+][trie[j][k]][]+=dp[i][j][],dp[i+][trie[j][k]][]%=mo;else
dp[i+][trie[j][k]][]+=dp[i][j][],dp[i+][trie[j][k]][]%=mo;
}
if (dp[i][j][]){
for (int k=;k<=;k++)
dp[i+][trie[j][k]][]+=dp[i][j][],dp[i+][trie[j][k]][]%=mo;
}
} int ans=;
for (int i=;i<=cnt;i++)
ans+=dp[m][i][],ans%=mo; printf("%d\n",ans);
}
自动机中一个节点对应了多个串,如此题中虽在字典树中非叶子节点,但可能对应了一个串
例:abab,ba,在到达找寻aba时实际已找到ba