#include <vector>   #include <array>   #include <stack>   #include <queue>   #include <list>   #include <bitset>   #include <set>   #include <map>   #include <unordered_set>   #include <unordered_map>   #include <algorithm>   #include <numeric>   #include <iostream>   #include <iomanip>   #include <string>   #include <chrono>   #include <random>   #include <cmath>   #include <cassert>   #include <climits>   #include <cstring>   #include <cstdlib>   #include <functional>   #include <sstream>      using namespace std;      const long long MOD = 998244353;      vector<vector<int>> matXmat(const vector<vector<int>>& A, const vector<vector<int>>& B, long long M = MOD) {       int n = A.size();       assert(n != 0);       assert(A[0].size() == B.size());       int l = B.size();       assert(l != 0);       int m = B[0].size();       assert(m != 0);          vector<vector<int>> res(n, vector<int>(m, 0));          long long MOD2 = M * 1LL * M;       for (int i = 0; i < n; ++i) {           for (int j = 0; j < l; ++j) {               for (int k = 0; k < m; ++k) {                   res[i][k] += A[i][j] * 1LL * B[j][k] % M;                   if (res[i][k] >= M) {                       res[i][k] -= M;                   }                   if (res[i][k] < 0) {                       res[i][k] += M;                   }               }           }       }       return res;   }         vector<long long> __tmpA(500, 0);   vector<vector<int>> matXmat2(const vector<vector<int>>& A, const vector<vector<int>>& B, long long M = MOD) {       int n = A.size();       assert(n != 0);       assert(A[0].size() == B.size());       int l = B.size();       assert(l != 0);       int m = B[0].size();       assert(m != 0);          vector<vector<int>> res(n, vector<int>(m, 0));          long long MOD2 = M * 1LL * M;       for (int i = 0; i < n; ++i) {           for (int k = 0; k < m; ++k) {               __tmpA[k] = 0;           }           for (int j = 0; j < l; ++j) {               for (int k = 0; k < m; ++k) {                   __tmpA[k] += A[i][j] * 1LL * B[j][k];                   if (__tmpA[k] >= MOD2) {                       __tmpA[k] -= MOD2;                   }               }           }           for (int k = 0; k < m; ++k) {               if (__tmpA[k] >= MOD) {                   res[i][k] = __tmpA[k] % MOD;               } else {                   res[i][k] = __tmpA[k];               }           }       }       return res;   }      vector<int> matXvec(const vector<vector<int>>& A, const vector<int>& B, long long M = MOD) {       int n = A.size();       assert(n != 0);       int m = A[0].size();       assert(m == B.size());          vector<int> res(n, 0);          long long MOD2 = M * 1LL * M;       for (int i = 0; i < n; ++i) {           long long ans = 0;           for (int j = 0; j < m; ++j) {               ans += A[i][j] * 1LL * B[j];               if (ans >= MOD2) {                   ans -= MOD2;               }               if (ans < 0) {                   ans += MOD2;               }           }           ans %= M;           if (ans < 0) {               ans += M;           }           res[i] = ans;       }       return res;   }      vector<vector<int>> matPow(vector<vector<int>> A, long long n, long long M = MOD) {       int m = A.size();       assert(m != 0 && A[0].size() == m);       vector<vector<int>> res(m, vector<int>(m, 0));       for (int i = 0; i < m; ++i) {           res[i][i] = 1;       }          while (n > 0) {           if (n & 1) {               res = matXmat2(res, A, M);           }           A = matXmat2(A, A, M);           n >>= 1;       }       return res;   }         class Trie{       public:           Trie(int n = 110000) : N(n), nodes(n), rt(-1), idx(-1) {               rt = newNode();           }              void reset() {               for (int i = 0; i <= idx; ++i) {                   nodes[i].reset();               }               idx = -1;               rt = newNode();           }                 int root() { return rt; }              int index(char ch) {               return ch -  a ;           }              void insert(string& s) {               int cur = rt;               for (auto c : s) {                   c = index(c);                   if (nodes[cur].nexts[c] == -1) {                       nodes[cur].nexts[c] = newNode();                   }                   cur = nodes[cur].nexts[c];                   nodes[cur].cnt += 1;               }               nodes[cur].isEnd = true;           }                 bool query(string& s) {               int cur = rt;               for (auto c : s) {                   c = index(c);                   if (nodes[cur].nexts[c] == -1) {                       return false;                   }                   cur = nodes[cur].nexts[c];               }               return nodes[cur].isEnd;           }              int next(int r, char ch) {               ch = index(ch);               return nodes[r].nexts[ch];           }              bool isEnd(int u) {               return nodes[u].isEnd;           }             private:           const static int A = 26;           struct Node {               Node() : cnt(0), isEnd(false) {                    fill(begin(nexts), end(nexts), -1);               }                  void reset() {                   cnt = 0;                   isEnd = false;                   fill(begin(nexts), end(nexts), -1);               }                  int nexts[A];               int cnt;               bool isEnd;           };              int N;           int rt;           int idx;           vector<Node> nodes;              int newNode() {               return ++idx;           }   };      class Solution {   public:       long long solve(vector<string>& S, int m) {           int n = S.size();              Trie tr(2000);           for (auto s : S) {               tr.insert(s);           }           const int N = 100;           vector<vector<vector<pair<int,int>>>> nexts(N, vector<vector<pair<int,int>>>(N));                      int rt = tr.root();           vector<pair<int,int>> que;           que.emplace_back(rt, rt);           vector<vector<bool>> ok(N, vector<bool>(N, false));           ok[rt][rt] = true;           vector<vector<bool>> visited(N, vector<bool>(N, false));           visited[rt][rt] = true;           for (int i = 0; i < que.size(); ++i) {               int u = que[i].first, v = que[i].second;                  for (int j =  a ; j <=  z ; ++j) {                   int nu = tr.next(u, j);                   int nv = tr.next(v, j);                   if (nu < 0 || nv < 0) {                       continue;                   }                   if (tr.isEnd(nu) && tr.isEnd(nv)) {                       nexts[u][v].emplace_back(rt, rt);                   }                   if (tr.isEnd(nu)) {                       nexts[u][v].emplace_back(rt, nv);                       if (!visited[rt][nv]) {                           visited[rt][nv] = true;                           que.emplace_back(rt, nv);                       }                   }                   if (tr.isEnd(nv)) {                       nexts[u][v].emplace_back(nu, rt);                       if (!visited[nu][rt]) {                           visited[nu][rt] = true;                           que.emplace_back(nu, rt);                       }                   }                   {                       nexts[u][v].emplace_back(nu, nv);                       if (!visited[nu][nv]) {                           visited[nu][nv] = true;                           que.emplace_back(nu, nv);                       }                   }               }           }                 while (true) {               int chg = 0;               for (auto& p : que) {                   int u = p.first, v = p.second;                   if (ok[u][v]) {                       continue;                   }                   for (auto& p2 : nexts[u][v]) {                       int nu = p2.first, nv = p2.second;                       if (ok[nu][nv]) {                           ok[u][v] = true;                           ++chg;                           break;                       }                                      }               }               if (chg == 0) {                   break;               }           }              map<pair<int,int>,int> indices;           for (auto& p : que) {               int u = p.first, v = p.second;               if (ok[u][v]) {                   int idx = indices.size();                   indices[p] = idx;               }           }               int sz = indices.size();           // cout <<  sz   << sz << endl;           vector<vector<int>> mat(sz, vector<int>(sz, 0));           for (auto& p : que) {               int u = p.first, v = p.second;               if (ok[u][v]) {                   for (auto& p2 : nexts[u][v]) {                       int nu = p2.first, nv = p2.second;                       if (ok[nu][nv]) {                           // cout << indices[p] <<     << indices[p2] <<     << u <<     << v <<  endl;                           mat[indices[p2]][indices[p]] += 1;                       }                   }               }           }              auto M = matPow(mat, m);              return M[0][0];       }   };      int main(int argc, char** argv) {       ios::sync_with_stdio(false);       cin.tie(0);          Solution sol;          int n, m;       cin >> n >> m;          vector<string> S(n);       for (int i = 0; i < n; ++i) {           cin >> S[i];       }          cout << sol.solve(S, m) <<   n ;          return 0;   }