#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define ti3 tuple<int,int,int>
const int inf = 1 << 30;
const ll mod = 998244353;
const ll linf = 1e18;
const db EPS = 1e-10;
const db pi = acos(-1);
template<class T> void chmin(T& x, T y){if(x > y) x = y;}
template<class T> void chmax(T& x, T y){if(x < y) x = y;}
#define mat vector<vector<int>>

mat matmul(const mat& a, const mat& b){
    int n1 = a.size(), m1 = a[0].size(), m2 = b[0].size();

    mat res;
    res.resize(n1, vector<int>(m2, 0));
    for(int i = 0; i < n1; i++){
        for(int j = 0; j < m2; j++){
            for(int k = 0; k < m1; k++){
                res[i][j] += (ll)a[i][k] * b[k][j] % mod;
                res[i][j] %= mod;
            }
        }
    }
    return res;
}

vector<int> matvec(const mat& m, const vector<int>& v) {
    vector<int> res(m.size(), 0);
    for (int i = 0; i < m.size(); i++) {
        for (int j = 0; j < v.size(); j++) {
            res[i] += (ll)m[i][j] * v[j] % mod;
            res[i] %= mod;
        }
    }
    return res;
}

mat matpow(mat m, ll y) {
    if (y == 0) {
        for (int i = 0; i < m.size(); i++) {
            for (int j = 0; j < m[i].size(); j++) {
                m[i][j] = (i == j ? 1 : 0);
            }
        }
        return m;
    }
    mat res = matpow(m, y / 2);
    res = matmul(res, res);
    if (y & 1) res = matmul(res, m);
    return res;
}

int n, m;
string word[10];
set<string> st;
vector<string> v = {""};
int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> word[i];
        for (int j = 1; j <= word[i].length(); j++) {
            string t = word[i].substr(0, j);
            if (st.find(t) == st.end()) {
                st.insert(t);
                v.push_back(t);
            }
        }
    }

    vector<pii> as = {{0, 0}};

    for (int i = 1; i < v.size(); i++) {
        for (int j = i; j < v.size(); j++) {
            string s = v[i], t = v[j];
            if (s.length() < t.length()) swap(s, t);
            if (s.substr(s.length() - t.length(), t.length()) == t) {
                as.push_back({i, j});
            }
        }
    }

    int sz = as.size();
    mat A = vector<vector<int>>(sz, vector<int>(sz, 0));
    vector<int> vs(sz, 0);

    for (int i = 0; i < sz; i++) {
        vs[i] = v[as[i].first].length() == 1 && v[as[i].second].length() == 1;
    }

    for (int i = 1; i < sz; i++) {
        bool flag[2] = {};
        for (int j = 0; j < n; j++) {
            if (v[as[i].first] == word[j]) flag[0] = 1;
            if (v[as[i].second] == word[j]) flag[1] = 1;
        }
        A[0][i] = flag[0] & flag[1];

        for (int j = 1; j < sz; j++) {
            auto judge = [&](string s, string t) -> int {
                if (s.length() == t.length() + 1 && s.substr(0, t.length()) == t) return 1;
                if (s.length() != 1) return 0;
                for (int i = 0; i < n; i++) {
                    if (t == word[i]) return 1;
                }
                return 0;
            };

            A[i][j] += judge(v[as[i].first], v[as[j].first]) & judge(v[as[i].second], v[as[j].second]);
            if (as[i].first != as[i].second) {
                A[i][j] += judge(v[as[i].first], v[as[j].second]) & judge(v[as[i].second], v[as[j].first]);
            }

        }
    }
    vs = matvec(matpow(A, m), vs);
    cout << vs[0] << endl;
}

/*
 *   ##   #####   ####      ####  #    #  ####
 *  #  #  #    # #    #    #    # #    # #    #
 * #    # #####  #         #    # #    # #    #
 * ###### #    # #         #    # # ## # #    #
 * #    # #    # #    #    #    # ##  ## #    #
 * #    # #####   ####      ####  #    #  ####
 */
#include <bits/stdc++.h>
using namespace std;
#define lli long long int
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define pii pair <int, int>
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define info() cout << __PRETTY_FUNCTION__ << ": " << __LINE__ << endl
void abc() {cout << endl;}
template <typename T, typename ...U> void abc(T a, U ...b) {
    cout << a << ' ', abc(b...);
}
template <typename T> void printv(T l, T r) {
    for (; l != r; ++l) cout << *l << " \n"[l + 1 == r];
}
template <typename A, typename B> istream& operator >> (istream& o, pair<A, B> &a) {
    return o >> a.X >> a.Y;
}
template <typename A, typename B> ostream& operator << (ostream& o, pair<A, B> a) {
    return o << '(' << a.X << ", " << a.Y << ')';
}
template <typename T> ostream& operator << (ostream& o, vector<T> a) {
    bool is = false;
    if (a.empty()) return o << "{}";
    for (T i : a) {o << (is ? ' ' : '{'), is = true, o << i;}
    return o << '}';
}
template <typename T> struct vv : vector <vector <T>> {
    vv(int n, int m, T v) : vector <vector <T>> (n, vector <T>(m, v)) {}
    vv() {}
};
template <typename T> struct vvv : vector <vv <T>> {
    vvv(int n, int m, int k, T v) : vector <vv <T>> (n, vv <T>(m, k, v)) {}
    vvv() {}
};
#ifdef Doludu
#define test(args...) abc("[" + string(#args) + "]", args)
#define owo freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout);
#else
#define test(args...) void(0)
#define owo ios::sync_with_stdio(false); cin.tie(0)
#endif
const int mod = 998244353, N = 300001, logN = 19, K = 1 << 9;

struct mat {
    int n;
    long long mod2;
    vector <vector <long long>> val;
    mat (int _n, int _mode = 0) : n(_n), mod2(1ll * mod * mod) {
        // mode 1 -> I, other -> O
        val.assign(n, vector<long long>(n, 0));
        if (_mode == 1) {
            for (int i = 0; i < n; ++i) val[i][i] = 1;
        }
    }
    mat (const mat& M) : n(M.n), mod2(1ll * mod * mod) {
        val.assign(n, vector<long long>(n, 0));
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                val[i][j] = M.val[i][j];
            }
        }
    }
    mat (vector <vector <long long>> v) : n(v.size()), mod2(1ll * mod * mod), val(v) {}
    mat operator + (const mat& o) {
        mat ans(o);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                ans.val[i][j] += val[i][j];
                if (ans.val[i][j] >= mod) ans.val[i][j] -= mod;
            }
        }
        return ans;
    }
    mat operator * (const mat& o) {
        mat ans(n, 0);
        for (int i = 0; i < n; ++i) {
            for (int k = 0; k < n; ++k) {
                for (int j = 0; j < n; ++j) {
                    ans.val[i][j] += val[i][k] * o.val[k][j];
                    if (ans.val[i][j] >= mod2) ans.val[i][j] -= mod2;
                }
            }
        }
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                ans.val[i][j] %= mod;
            }
        }
        return ans;
    }
    mat operator ^ (long long k) {
        mat ans(n, 1), a(*this);
        for (; k; k >>= 1, a = a * a) {
            if (k & 1) ans = ans * a;
        }
        return ans;
    }
};

int main() {
    owo;
    int n, m;
    cin >> n >> m;
    vector <string> pre;
    vector <int> fin;
    pre.pb(""), fin.pb(0);
    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 1; j <= s.length(); ++j) {
            if (find(all(pre), s.substr(0, j)) == pre.end()) {
                pre.pb(s.substr(0, j)), fin.pb(0);
            }
        }
        fin[find(all(pre), s) - pre.begin()] = 1;
    }
    vector <pii> dim;
    for (int i = 0; i < pre.size(); ++i) {
        for (int j = 0; j < pre.size(); ++j) {
            string s = pre[i], t = pre[j];
            if (s.length() > t.length())
                swap(s, t);
            if (t.substr(t.length() - s.length()) == s) {
                dim.eb(i, j);
            }
        }
    }
    auto append = [&](int i, char c) {
        if (find(all(pre), pre[i] + c) != pre.end()) {
            return find(all(pre), pre[i] + c) - pre.begin();
        }
        return -1;
    };
    n = dim.size();
    vv <long long> a(n, n, 0);
    function<void(int, int, int)> add_ma = [&](int i, int l, int r) {
        if (find(all(dim), mp(l, r)) != dim.end())
            a[i][find(all(dim), mp(l, r)) - dim.begin()]++;
        if (fin[l])
            add_ma(i, 0, r);
        if (fin[r])
            add_ma(i, l, 0);
        if (fin[l] && fin[r])
            a[i][0]--;
    };
    for (int i = 0; i < n; ++i) {
        for (char c = 'a'; c <= 'z'; ++c) {
            int l, r;
            tie(l, r) = dim[i];
            l = append(l, c), r = append(r, c);
            if (l == -1 || r == -1)
                continue;
            add_ma(i, l, r);
        }
    }
    mat M(a);
    M = M ^ m;
    cout << M.val[0][0] << endl;
}

/* https://csacademy.com/submission/2759503/ (rainboy) */
#include <stdio.h>
#include <string.h>

#define N	8
#define L	5
#define N_	(1 + N * L)
#define N1	(N_ * 2)
#define A	26
#define MD	998244353

int tt[1 + N_][A]; char word[1 + N_];

void dfs(int coef[][L + 1], int s1, int s2, int l) {
	int a;

	if (s1 == 0 || s2 == 0)
		return;
	if (l > 0) {
		if (word[s1])
			coef[s2 - 1 << 1 | 0][l]++;
		if (word[s2])
			coef[s1 - 1 << 1 | 1][l]++;
		if (word[s1] && word[s2])
			coef[0][l]++;
	}
	for (a = 0; a < A; a++)
		dfs(coef, tt[s1][a], tt[s2][a], l + 1);
}

int coef[N1][N1][L + 1];

void apply(int aa[][N1][L], int n) {
	static int bb[N1][N1];
	int i, j, k, l;

	for (i = 0; i < n; i++)
		memset(bb[i], 0, n * sizeof *bb[i]);
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			for (k = 0; k < n; k++)
				for (l = 1; l <= L; l++)
					bb[i][k] = (bb[i][k] + (long long) aa[i][j][l - 1] * coef[j][k][l]) % MD;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			for (l = L - 1; l >= 0; l--)
				aa[i][j][l] = l == 0 ? bb[i][j] : aa[i][j][l - 1];
}

void mult(int aa[][N1][L], int bb[][N1][L], int cc[][N1][L], int n) {
	static int aa_[N1][N1][L], bb_[N1][N1][L + L];
	int i, j, k, l, l1, l2;

	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			memcpy(aa_[i][j], aa[i][j], L * sizeof *aa[i][j]);
	for (l = 0; l < L; l++)
		for (i = 0; i < n; i++)
			for (j = 0; j < n; j++)
				for (k = 0; k < n; k++)
					for (l1 = 1; l + l1 < L; l1++)
						aa_[i][k][l] = (aa_[i][k][l] - (long long) aa_[i][j][l + l1] * coef[j][k][l1]) % MD;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++) {
			memset(bb_[i][j], 0, L * sizeof *bb_[i][j]);
			memcpy(bb_[i][j] + L, bb[i][j], L * sizeof *bb[i][j]);
		}
	for (l = L - 1; l >= 0; l--)
		for (i = 0; i < n; i++)
			for (j = 0; j < n; j++)
				for (k = 0; k < n; k++)
					for (l1 = 1; l1 <= L; l1++)
						bb_[i][k][l] = (bb_[i][k][l] + (long long) coef[i][j][l1] * bb_[j][k][l + l1]) % MD;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			memset(cc[i][j], 0, L * sizeof *cc[i][j]);
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			for (k = 0; k < n; k++)
				for (l1 = 0; l1 < L; l1++)
					for (l2 = L - l1; l1 + l2 - L < L; l2++)
						cc[i][k][l1 + l2 - L] = (cc[i][k][l1 + l2 - L] + (long long) aa_[i][j][l1] * bb_[j][k][l2]) % MD;
}

void power(int pp[][N1][L], int tt[][N1][L], int n, int k) {
	int i, j, l;

	if (k == 0) {
		for (i = 0; i < n; i++)
			for (j = 0; j < n; j++)
				for (l = 0; l < L; l++)
					pp[i][j][l] = i == j && l == 0;
		return;
	}
	power(tt, pp, n, k / 2);
	mult(tt, tt, pp, n);
	if (k & 1)
		apply(pp, n);
}

int main() {
	static int pp[N1][N1][L], tt_[N1][N1][L];
	int n, n_, k, i, s;

	scanf("%d%d", &n, &k);
	n_ = 1;
	for (i = 0; i < n; i++) {
		static char cc[L + 1];
		int l, h;

		scanf("%s", cc), l = strlen(cc);
		for (h = 0, s = 1; h < l; h++) {
			int a = cc[h] - 'a';

			if (!tt[s][a])
				tt[s][a] = ++n_;
			s = tt[s][a];
		}
		word[s] = 1;
	}
	for (s = 0; s < n_; s++) {
		dfs(coef[s << 1 | 0], 1, s + 1, 0);
		if (s != 0)
			dfs(coef[s << 1 | 1], s + 1, 1, 0);
	}
	power(pp, tt_, n_ * 2, k);
	if (pp[0][0][0] < 0)
		pp[0][0][0] += MD;
	printf("%d\n", pp[0][0][0]);
	return 0;
}

#line 1 "codeforces-workspace/contest/1511/f/f.cpp"
// #undef _GLIBCXX_DEBUG
// #define NDEBUG
#include <bits/extc++.h>

#line 2 "Library/lib/alias"

/**
 * @file alias
 * @brief Alias
 */

#line 13 "Library/lib/alias"

#line 2 "Library/lib/bit"

#if __cplusplus > 201703L

#include <bit>

#else

#ifndef _GLIBCXX_BIT
#define _GLIBCXX_BIT 1

#include <limits>
#include <type_traits>

namespace std {

template <typename _Tp> constexpr _Tp __rotl(_Tp __x, int __s) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  const int __r = __s % _Nd;
  if (__r == 0)
    return __x;
  else if (__r > 0)
    return (__x << __r) | (__x >> ((_Nd - __r) % _Nd));
  else
    return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd));  // rotr(x, -r)
}

template <typename _Tp> constexpr _Tp __rotr(_Tp __x, int __s) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  const int __r = __s % _Nd;
  if (__r == 0)
    return __x;
  else if (__r > 0)
    return (__x >> __r) | (__x << ((_Nd - __r) % _Nd));
  else
    return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd));  // rotl(x, -r)
}

template <typename _Tp> constexpr int __countl_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) {
    constexpr int __diff = _Nd_u - _Nd;
    return __builtin_clz(__x) - __diff;
  } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) {
    constexpr int __diff = _Nd_ul - _Nd;
    return __builtin_clzl(__x) - __diff;
  } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) {
    constexpr int __diff = _Nd_ull - _Nd;
    return __builtin_clzll(__x) - __diff;
  } else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    unsigned long long __high = __x >> _Nd_ull;
    if (__high != 0) {
      constexpr int __diff = (2 * _Nd_ull) - _Nd;
      return __builtin_clzll(__high) - __diff;
    }
    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    return (_Nd - _Nd_ull) + __builtin_clzll(__low);
  }
}

template <typename _Tp> constexpr int __countl_one(_Tp __x) noexcept {
  if (__x == numeric_limits<_Tp>::max()) return numeric_limits<_Tp>::digits;
  return __countl_zero<_Tp>((_Tp)~__x);
}

template <typename _Tp> constexpr int __countr_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
    return __builtin_ctz(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
    return __builtin_ctzl(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
    return __builtin_ctzll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    if (__low != 0) return __builtin_ctzll(__low);
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_ctzll(__high) + _Nd_ull;
  }
}

template <typename _Tp> constexpr int __countr_one(_Tp __x) noexcept {
  if (__x == numeric_limits<_Tp>::max()) return numeric_limits<_Tp>::digits;
  return __countr_zero((_Tp)~__x);
}

template <typename _Tp> constexpr int __popcount(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return 0;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
    return __builtin_popcount(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
    return __builtin_popcountl(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
    return __builtin_popcountll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_popcountll(__low) + __builtin_popcountll(__high);
  }
}

template <typename _Tp> constexpr bool __has_single_bit(_Tp __x) noexcept {
  return __popcount(__x) == 1;
}

template <typename _Tp> constexpr _Tp __bit_ceil(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0 || __x == 1) return 1;
  auto __shift_exponent = _Nd - __countl_zero((_Tp)(__x - 1u));
#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
  if (!__builtin_is_constant_evaluated()) {
    __glibcxx_assert(__shift_exponent != numeric_limits<_Tp>::digits);
  }
#endif
  using __promoted_type = decltype(__x << 1);
  if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) {
    const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2;
    __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp;
  }
  return (_Tp)1u << __shift_exponent;
}

template <typename _Tp> constexpr _Tp __bit_floor(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0) return 0;
  return (_Tp)1u << (_Nd - __countl_zero((_Tp)(__x >> 1)));
}

template <typename _Tp> constexpr _Tp __bit_width(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  return _Nd - __countl_zero(__x);
}

}  // namespace std

#endif

#endif
#line 2 "Library/lib/limits"

#line 4 "Library/lib/limits"

namespace workspace {

template <class _Tp> struct numeric_limits : std::numeric_limits<_Tp> {};

#ifdef __SIZEOF_INT128__

template <> struct numeric_limits<__uint128_t> {
  constexpr static __uint128_t max() { return ~__uint128_t(0); }
  constexpr static __uint128_t min() { return 0; }
};

template <> struct numeric_limits<__int128_t> {
  constexpr static __int128_t max() {
    return numeric_limits<__uint128_t>::max() >> 1;
  }
  constexpr static __int128_t min() { return -max() - 1; }
};

#endif

}  // namespace workspace
#line 16 "Library/lib/alias"

namespace workspace {

constexpr char eol = '\n';

using namespace std;

using i32 = int_least32_t;
using u32 = uint_least32_t;
using i64 = int_least64_t;
using u64 = uint_least64_t;

#ifdef __SIZEOF_INT128__
using i128 = __int128_t;
using u128 = __uint128_t;
#else
#warning 128bit integer is not available.
#endif

namespace _alias_impl {

template <class> struct first_arg { using type = void; };

template <class _Tp, class = void> struct parse_comp : first_arg<_Tp> {};

template <class _Tp>
struct parse_comp<_Tp, std::__void_t<decltype(&_Tp::operator())>>
    : first_arg<decltype(&_Tp::operator())> {};

template <class _R, class _Tp, class... _Args>
struct first_arg<_R(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _R, class _Tp, class... _Args>
struct first_arg<_R (*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...) const> {
  using type = _Tp;
};

}  // namespace _alias_impl

template <class _Tp = void, class _Compare = std::less<_Tp>>
decltype(auto) make_priority_queue(_Compare __x = _Compare()) noexcept {
  using type = std::conditional_t<
      std::is_void<_Tp>::value,
      std::decay_t<typename _alias_impl::parse_comp<_Compare>::type>, _Tp>;

  return std::priority_queue<type, std::vector<type>, _Compare>(__x);
}

template <class _Tp = void, class _Compare = std::less<_Tp>>
decltype(auto) make_set(_Compare __x = _Compare()) noexcept {
  using type = std::conditional_t<
      std::is_void<_Tp>::value,
      std::decay_t<typename _alias_impl::parse_comp<_Compare>::type>, _Tp>;

  return std::set<type, _Compare>(__x);
}

template <class _Key, class _Mapped, class _Compare = std::less<_Key>>
decltype(auto) make_map(_Compare __x = _Compare()) noexcept {
  return std::map<_Key, _Mapped, _Compare>(__x);
}

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T2 &>() <
                              std::declval<const _T1 &>())>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y) noexcept {
  return __y < __x ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T2 &>(), std::declval<const _T1 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__y, __x) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp min(std::initializer_list<_Tp> __x) noexcept {
  return *std::min_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp min(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::min_element(__x.begin(), __x.end(), __comp);
}

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T1 &>() <
                              std::declval<const _T2 &>())>

constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y) noexcept {
  return __x < __y ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T1 &>(), std::declval<const _T2 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__x, __y) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp max(std::initializer_list<_Tp> __x) noexcept {
  return *std::max_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp max(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::max_element(__x.begin(), __x.end(), __comp);
}

template <typename _Tp> constexpr _Tp __bsf(_Tp __x) noexcept {
  return std::__countr_zero(__x);
}

template <typename _Tp> constexpr _Tp __bsr(_Tp __x) noexcept {
  return std::__bit_width(__x) - 1;
}

}  // namespace workspace
#line 6 "codeforces-workspace/contest/1511/f/f.cpp"
// #include "lib/cxx20"
#line 2 "Library/lib/direct"

/*
 * @file direct
 * @brief Pragma Directive
 */

#ifdef ONLINE_JUDGE

#pragma GCC optimize("O3")
#pragma GCC target("avx,avx2")
#pragma GCC optimize("unroll-loops")

#endif
#line 8 "codeforces-workspace/contest/1511/f/f.cpp"
// #include "lib/opt"
#line 2 "Library/src/sys/clock.hpp"

/*
 * @fn clock.hpp
 * @brief Clock
 */

#line 9 "Library/src/sys/clock.hpp"

namespace workspace {

using namespace std::chrono;

namespace internal {
// The start time of the program.
const auto start_time{system_clock::now()};
}  // namespace internal

/*
 * @fn elapsed
 * @return elapsed time of the program
 */
int64_t elapsed() {
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - internal::start_time).count();
}

}  // namespace workspace
#line 2 "Library/src/sys/ejection.hpp"

/**
 * @file ejection.hpp
 * @brief Ejection
 */

#line 9 "Library/src/sys/ejection.hpp"

namespace workspace {

namespace internal {

struct ejection {
  bool exit = 0;
};

}  // namespace internal

/**
 * @brief eject from a try block, throw nullptr
 * @param arg output
 */
template <class Tp> void eject(Tp const &arg) {
  std::cout << arg << "\n";
  throw internal::ejection{};
}

void exit() { throw internal::ejection{true}; }

}  // namespace workspace
#line 2 "Library/src/sys/iteration.hpp"

/**
 * @file iteration.hpp
 * @brief Case Iteration
 */

#line 9 "Library/src/sys/iteration.hpp"

#line 11 "Library/src/sys/iteration.hpp"

namespace workspace {

void main();

struct {
  // 1-indexed
  unsigned current{0};
  unsigned total{1};

  void read() { (std::cin >> total).ignore(); }

  int iterate() {
    static bool once = false;
    assert(!once);
    once = true;
    while (current++ < total) {
      try {
        main();
      } catch (internal::ejection const& status) {
        if (status.exit) break;
      }
    }
    return 0;
  }
} case_info;

}  // namespace workspace
#line 10 "codeforces-workspace/contest/1511/f/f.cpp"
// #include "lib/utils"

#line 2 "Library/src/utils/io/setup.hpp"

/**
 * @file setup.hpp
 * @brief I/O Setup
 */

#line 10 "Library/src/utils/io/setup.hpp"

namespace workspace {

/**
 * @brief Setup I/O.
 * @param __n Standard output precision
 */
void io_setup(int __n) {
  std::cin.tie(0)->sync_with_stdio(0);
  std::cout << std::fixed << std::setprecision(__n);

#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (std::cin >> bufc)
      std::cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}

}  // namespace workspace
#line 2 "Library/src/utils/py-like/range.hpp"

/**
 * @file range.hpp
 * @brief Range
 */

#line 9 "Library/src/utils/py-like/range.hpp"

#line 2 "Library/src/utils/iterator/reverse.hpp"

/*
 * @file reverse_iterator.hpp
 * @brief Reverse Iterator
 */

#if __cplusplus >= 201703L

#include <iterator>
#include <optional>

namespace workspace {

/*
 * @class reverse_iterator
 * @brief Wrapper class for `std::reverse_iterator`.
 * @see http://gcc.gnu.org/PR51823
 */
template <class Iterator>
class reverse_iterator : public std::reverse_iterator<Iterator> {
  using base_std = std::reverse_iterator<Iterator>;
  std::optional<typename base_std::value_type> deref;

 public:
  using base_std::reverse_iterator;

  constexpr typename base_std::reference operator*() noexcept {
    if (!deref) {
      Iterator tmp = base_std::current;
      deref = *--tmp;
    }
    return deref.value();
  }

  constexpr reverse_iterator &operator++() noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator &operator--() noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator operator++(int) noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator operator--(int) noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
};

}  // namespace workspace

#endif
#line 2 "Library/src/utils/py-like/reversed.hpp"

/**
 * @file reversed.hpp
 * @brief Reversed
 */

#include <initializer_list>
#line 10 "Library/src/utils/py-like/reversed.hpp"

namespace workspace {

namespace _reversed_impl {

template <class _Container> class reversed {
  _Container __cont;

 public:
  constexpr reversed(_Container &&__cont) noexcept : __cont(__cont) {}

  constexpr decltype(auto) begin() noexcept { return std::rbegin(__cont); }
  constexpr decltype(auto) begin() const noexcept {
    return std::rbegin(__cont);
  }

  constexpr decltype(auto) end() noexcept { return std::rend(__cont); }
  constexpr decltype(auto) end() const noexcept { return std::rend(__cont); }

  constexpr decltype(auto) size() const noexcept { return std::size(__cont); }
};

}  // namespace _reversed_impl

template <class _Container>
constexpr decltype(auto) reversed(_Container &&__cont) noexcept {
  return _reversed_impl::reversed<_Container>{std::forward<_Container>(__cont)};
}

template <class _Tp>
constexpr decltype(auto) reversed(
    std::initializer_list<_Tp> &&__cont) noexcept {
  return _reversed_impl::reversed<std::initializer_list<_Tp>>{
      std::forward<std::initializer_list<_Tp>>(__cont)};
}

}  // namespace workspace
#line 12 "Library/src/utils/py-like/range.hpp"

#if __cplusplus >= 201703L

namespace workspace {

template <class _Index> class range {
  _Index __first, __last;

 public:
  class iterator {
    _Index current;

   public:
    using difference_type = std::ptrdiff_t;
    using value_type = _Index;
    using reference = typename std::add_const<_Index>::type &;
    using pointer = iterator;
    using iterator_category = std::bidirectional_iterator_tag;

    constexpr iterator(const _Index &__i = _Index()) noexcept : current(__i) {}

    constexpr bool operator==(const iterator &__x) const noexcept {
      return current == __x.current;
    }
    constexpr bool operator!=(const iterator &__x) const noexcept {
      return current != __x.current;
    }

    constexpr iterator &operator++() noexcept {
      ++current;
      return *this;
    }
    constexpr iterator &operator--() noexcept {
      --current;
      return *this;
    }

    constexpr reference operator*() const noexcept { return current; }
  };

  constexpr range(_Index __first, _Index __last) noexcept
      : __first(__first), __last(__last) {}
  constexpr range(_Index __last) noexcept : __first(), __last(__last) {}

  constexpr iterator begin() const noexcept { return iterator{__first}; }
  constexpr iterator end() const noexcept { return iterator{__last}; }

  constexpr reverse_iterator<iterator> rbegin() const noexcept {
    return reverse_iterator<iterator>(end());
  }
  constexpr reverse_iterator<iterator> rend() const noexcept {
    return reverse_iterator<iterator>(begin());
  }

  constexpr size_t size() const noexcept {
    return std::distance(__first, __last);
  }
};

template <class... _Args>
constexpr decltype(auto) rrange(_Args &&...__args) noexcept {
  return reversed(range(std::forward<_Args>(__args)...));
}

}  // namespace workspace

#endif
#line 14 "codeforces-workspace/contest/1511/f/f.cpp"

signed main() {
  using namespace workspace;

  io_setup(15);

  /* given
    case_info.read();  //*/

  /* unspecified
    case_info.total = -1;  //*/

  return case_info.iterate();
}

#line 2 "Library/src/algebra/linear/matrix.hpp"

/**
 * @file matrix.hpp
 * @brief Matrix
 * @date 2021-02-15
 *
 *
 */

#line 13 "Library/src/algebra/linear/matrix.hpp"

namespace workspace {

/**
 * @brief Fixed size matrix.
 *
 * @tparam _Scalar
 * @tparam _Rows Number of rows
 * @tparam _Cols Number of columns
 */
template <class _Scalar, std::size_t _Rows = 0, std::size_t _Cols = _Rows>
class matrix {
 public:
  _Scalar __data[_Rows][_Cols] = {};

  using value_type = _Scalar;
  using size_type = std::size_t;

  constexpr static matrix eye() {
    static_assert(_Rows == _Cols);

    matrix __e;
    for (size_type __d = 0; __d != _Rows; ++__d) __e.__data[__d][__d] = 1;
    return __e;
  }

  constexpr operator decltype((__data))() { return __data; }
  constexpr operator decltype(std::declval<const matrix>().__data)
      const&() const {
    return __data;
  }

  constexpr auto begin() { return __data; }
  constexpr auto begin() const { return __data; }

  constexpr auto end() { return __data + _Rows; }
  constexpr auto end() const { return __data + _Rows; }

  constexpr size_type rows() const { return _Rows; }

  constexpr size_type cols() const { return _Cols; }

  constexpr auto transpose() const {
    matrix<_Scalar, _Cols, _Rows> __t;

    for (size_type __r = 0; __r != _Rows; ++__r)
      for (size_type __c = 0; __c != _Cols; ++__c)
        __t.__data[__c][__r] = __data[__r][__c];

    return __t;
  }

  constexpr matrix operator+() const { return *this; }

  constexpr matrix operator-() const {
    matrix __cp = *this;

    for (auto& __v : __cp.__data)
      for (auto& __e : __v) __e = -__e;

    return __cp;
  }

  template <class _Matrix> constexpr matrix& operator+=(const _Matrix& __x) {
    auto __m = std::min(_Rows, __x.rows());
    auto __n = std::min(_Cols, __x.cols());

    for (size_type __r = 0; __r != __m; ++__r)
      for (size_type __c = 0; __c != __n; ++__c)
        __data[__r][__c] += __x[__r][__c];

    return *this;
  }

  template <class _Matrix>
  constexpr matrix operator+(const _Matrix& __x) const {
    return matrix(*this) += __x;
  }

  template <class _Matrix> constexpr matrix& operator-=(const _Matrix& __x) {
    auto __m = std::min(_Rows, __x.rows());
    auto __n = std::min(_Cols, __x.cols());

    for (size_type __r = 0; __r != __m; ++__r)
      for (size_type __c = 0; __c != __n; ++__c)
        __data[__r][__c] -= __x[__r][__c];

    return *this;
  }

  template <class _Matrix>
  constexpr matrix operator-(const _Matrix& __x) const {
    return matrix(*this) -= __x;
  }

  template <class _Scalar2>
  constexpr matrix& operator*=(const matrix<_Scalar2, _Cols, _Cols>& __x) {
    if (this == &__x) return operator=(operator*(__x));

    for (auto& __r : __data) {
      _Scalar __tmp[_Cols] = {};

      auto __v = *__x.__data;
      for (auto& __w : __tmp) {
        auto __i = __v++;
        for (const auto& __e : __r) __w += __e * *__i, __i += _Cols;
      }

      auto __w = __tmp;
      for (auto& __e : __r) __e = std::move(*__w++);
    }

    return *this;
  }

  template <class _Scalar2, size_type _Rows2, size_type _Cols2>
  constexpr auto operator*(const matrix<_Scalar2, _Rows2, _Cols2>& __x) const {
    matrix<typename std::common_type<_Scalar, _Scalar2>::type, _Rows, _Cols2>
        __m;

    auto __w = *__m.__data;
    for (const auto& __r : __data)
      for (auto __v = *__x.__data, __v_end = __v + _Cols2; __v != __v_end;
           ++__w) {
        auto __i = __v++;
        for (auto __e = __r; __e != __r + std::min(_Cols, _Rows2); ++__e)
          *__w += *__e * *__i, __i += _Cols2;
      }

    return __m;
  }

  template <class _Matrix>
  constexpr
      typename std::enable_if<!std::is_convertible<_Matrix, value_type>::value,
                              matrix<_Scalar>>::type
      operator*(const _Matrix& __x) const {
    matrix<_Scalar> __m(_Rows, __x.cols());

    for (size_type __r = 0; __r != _Rows; ++__r)
      for (size_type __i = 0; __i != __x.cols(); ++__i)
        for (size_type __c = 0; __c != std::min(_Cols, __x.rows()); ++__c)
          __m[__r][__i] += __data[__r][__c] * __x[__c][__i];

    return __m;
  }

  constexpr matrix& operator*=(const value_type& __x) {
    for (auto& __v : __data)
      for (auto& __e : __v) __e *= __x;

    return *this;
  }

  constexpr matrix operator*(const value_type& __x) const {
    return matrix(*this) *= __x;
  }

  constexpr matrix& operator/=(const value_type& __x) {
    assert(__x != value_type(0));

    for (auto& __v : __data)
      for (auto& __e : __v) __e /= __x;

    return *this;
  }

  constexpr matrix operator/(const value_type& __x) const {
    return matrix(*this) /= __x;
  }

  template <class _Int> constexpr matrix pow(_Int __e) const {
    assert(0 <= __e);

    matrix __m = eye();
    for (matrix __cp = *this; __e; __cp *= __cp, __e >>= 1)
      if (__e & 1) __m *= __cp;

    return __m;
  }

  template <class _Os>
  constexpr friend _Os& operator<<(_Os& __os, const matrix& __x) {
    for (auto __i = __x.begin(); __i != __x.end(); ++__i, __os << '\n')
      for (size_type __c = 0; __c != _Cols; ++__c)
        __c ? void(__os << ' ') : (void)0, __os << *(*__i + __c);

    return __os;
  }
};  // namespace workspace

/**
 * @brief Dynamic matrix.
 *
 * @tparam _Scalar
 * @tparam _Rows Number of rows
 * @tparam _Cols Number of columns
 */
template <class _Scalar>
class matrix<_Scalar, 0, 0> : public std::valarray<std::valarray<_Scalar>> {
  using base = std::valarray<std::valarray<_Scalar>>;
  using row_type = typename base::value_type;

 public:
  using value_type = _Scalar;
  using size_type = std::size_t;

  using base::operator[];

  static matrix eye(size_type __n) {
    matrix __e(__n, __n);
    for (size_type __d = 0; __d != __n; ++__d) __e[__d][__d] = 1;
    return __e;
  }

  matrix() = default;

  matrix(size_type __n) : matrix(__n, __n) {}

  matrix(size_type __m, size_type __n) : base(row_type(__n), __m) {}

  template <class _Tp, typename = typename std::enable_if<
                           std::is_constructible<base, _Tp>::value &&
                           !std::is_constructible<size_type, _Tp>::value>::type>
  matrix(_Tp&& __x) : base(__x) {}

  matrix(std::initializer_list<row_type> __x) : base(__x) {}

  size_type rows() const { return base::size(); }

  size_type cols() const { return rows() ? operator[](0).size() : 0; }

  matrix transpose() const {
    matrix __t(cols(), rows());

    for (size_type __r = 0; __r != rows(); ++__r)
      for (size_type __c = 0; __c != cols(); ++__c)
        __t[__c][__r] = operator[](__r)[__c];

    return __t;
  }

  void resize(size_type __m, size_type __n) {
    matrix __t(__m, __n);

    if (rows() < __m) __m = rows();
    if (cols() < __n) __n = cols();

    for (size_type __r = 0; __r != __m; ++__r)
      for (size_type __c = 0; __c != __n; ++__c)
        __t[__r][__c] = std::move(operator[](__r)[__c]);

    base::swap(__t);
  }

  // binary operators {{

  template <class _Matrix, typename = void>
  struct is_valarray_based : std::false_type {};

  template <class _Matrix>
  struct is_valarray_based<
      _Matrix,
      typename std::enable_if<std::is_same<
          row_type, typename std::decay<decltype(
                        std::declval<_Matrix>()[0])>::type>::value>::type>
      : std::true_type {};

  template <class _Matrix>
  typename std::enable_if<!std::is_convertible<_Matrix, value_type>::value,
                          matrix&>::type
  operator*=(_Matrix&& __x) {
    return *this = operator*(std::forward<_Matrix>(__x));
  }

  template <class _Matrix>
  typename std::enable_if<!std::is_convertible<_Matrix, value_type>::value,
                          matrix>::type
  operator*(const _Matrix& __x) const {
    matrix __m(rows(), __x.cols());

    if constexpr (is_valarray_based<_Matrix>::value)
      for (size_type __r = 0; __r != rows(); ++__r)
        for (size_type __c = 0; __c != std::min(cols(), __x.rows()); ++__c)
          __m[__r] += operator[](__r)[__c] * __x[__c];

    else
      for (size_type __r = 0; __r != rows(); ++__r)
        for (size_type __i = 0; __i != __x.cols(); ++__i)
          for (size_type __c = 0; __c != std::min(cols(), __x.rows()); ++__c)
            __m[__r][__i] += operator[](__r)[__c] * __x[__c][__i];

    return __m;
  }

  matrix& operator*=(const value_type& __x) {
    for (size_type __r = 0; __r != rows(); ++__r)
      operator[](__r).operator*=(__x);

    return *this;
  }

  matrix operator*(const value_type& __x) const { return matrix(*this) *= __x; }

  friend matrix operator*(const value_type& __x, matrix __i) {
    for (size_type __r = 0; __r != __i.rows(); ++__r)
      __i.operator[](__r) = __x * __i.operator[](__r);

    return __i;
  }

  matrix& operator/=(const value_type& __x) {
    assert(__x != value_type(0));

    for (size_type __r = 0; __r != rows(); ++__r)
      operator[](__r).operator/=(__x);

    return *this;
  }

  matrix operator/(const value_type& __x) const { return matrix(*this) /= __x; }

  // }} binary operators

  template <class _Int> matrix pow(_Int __e) const {
    assert(0 <= __e);

    matrix __m = eye(rows());
    for (matrix __cp = *this; __e; __cp *= __cp, __e >>= 1)
      if (__e & 1) __m *= __cp;

    return __m;
  }

  // template <class _Is> friend _Is& operator>>(_Is& __is, matrix& __x) {
  //   for (size_type __r = 0; __r != __x.rows(); ++__r)
  //     for (size_type __c = 0; __c != __x.cols(); ++__c)
  //       __is >> __x.operator[](__r).operator[](__c);

  //   return __is;
  // }

  template <class _Os> friend _Os& operator<<(_Os& __os, const matrix& __x) {
    for (size_type __r = 0; __r != __x.rows(); ++__r, __os << '\n')
      for (size_type __c = 0; __c != __x.cols(); ++__c)
        __c ? void(__os << ' ') : (void)0,
            __os << __x.operator[](__r).operator[](__c);

    return __os;
  }
};

}  // namespace workspace
#line 2 "Library/src/modular/modint.hpp"

/**
 * @file modint.hpp
 *
 * @brief Modular Arithmetic
 */

#line 12 "Library/src/modular/modint.hpp"

#line 2 "Library/src/number_theory/sqrt_mod.hpp"

/**
 * @file sqrt_mod.hpp
 * @brief Tonelli-Shanks Algorithm
 */

#line 2 "Library/src/number_theory/pow_mod.hpp"

/**
 * @file mod_pow.hpp
 * @brief Modular Exponentiation
 */

#line 9 "Library/src/number_theory/pow_mod.hpp"

#line 2 "Library/src/utils/sfinae.hpp"

/**
 * @file sfinae.hpp
 * @brief SFINAE
 */

#line 10 "Library/src/utils/sfinae.hpp"
#include <type_traits>

#ifndef __INT128_DEFINED__

#ifdef __SIZEOF_INT128__
#define __INT128_DEFINED__ 1
#else
#define __INT128_DEFINED__ 0
#endif

#endif

namespace std {

#if __INT128_DEFINED__

template <> struct make_signed<__uint128_t> { using type = __int128_t; };
template <> struct make_signed<__int128_t> { using type = __int128_t; };

template <> struct make_unsigned<__uint128_t> { using type = __uint128_t; };
template <> struct make_unsigned<__int128_t> { using type = __uint128_t; };

template <> struct is_signed<__uint128_t> : std::false_type {};
template <> struct is_signed<__int128_t> : std::true_type {};

template <> struct is_unsigned<__uint128_t> : std::true_type {};
template <> struct is_unsigned<__int128_t> : std::false_type {};

#endif

}  // namespace std

namespace workspace {

template <class Tp, class... Args> struct variadic_front { using type = Tp; };

template <class... Args> struct variadic_back;

template <class Tp> struct variadic_back<Tp> { using type = Tp; };

template <class Tp, class... Args> struct variadic_back<Tp, Args...> {
  using type = typename variadic_back<Args...>::type;
};

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

/**
 * @brief Return type of subscripting ( @c [] ) access.
 */
template <class _Tp>
using subscripted_type =
    typename std::decay<decltype(std::declval<_Tp&>()[0])>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class _Tp, class = std::nullptr_t>
struct has_begin : std::false_type {};

template <class _Tp>
struct has_begin<_Tp, decltype(std::begin(std::declval<_Tp>()), nullptr)>
    : std::true_type {};

template <class _Tp, class = std::nullptr_t>
struct has_mod : std::false_type {};

template <class _Tp>
struct has_mod<_Tp, decltype(_Tp::mod, nullptr)> : std::true_type {};

template <class _Tp, class = void> struct is_integral_ext : std::false_type {};
template <class _Tp>
struct is_integral_ext<
    _Tp, typename std::enable_if<std::is_integral<_Tp>::value>::type>
    : std::true_type {};

#if __INT128_DEFINED__

template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};

#endif

#if __cplusplus >= 201402

template <class _Tp>
constexpr static bool is_integral_ext_v = is_integral_ext<_Tp>::value;

#endif

template <typename _Tp, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename _Tp>
struct multiplicable_uint<
    _Tp,
    typename std::enable_if<(2 < sizeof(_Tp)) &&
                            (!__INT128_DEFINED__ || sizeof(_Tp) <= 4)>::type> {
  using type = uint_least64_t;
};

#if __INT128_DEFINED__

template <typename _Tp>
struct multiplicable_uint<_Tp,
                          typename std::enable_if<(4 < sizeof(_Tp))>::type> {
  using type = __uint128_t;
};

#endif

template <typename _Tp> struct multiplicable_int {
  using type =
      typename std::make_signed<typename multiplicable_uint<_Tp>::type>::type;
};

template <typename _Tp> struct multiplicable {
  using type = std::conditional_t<
      is_integral_ext<_Tp>::value,
      std::conditional_t<std::is_signed<_Tp>::value,
                         typename multiplicable_int<_Tp>::type,
                         typename multiplicable_uint<_Tp>::type>,
      _Tp>;
};

}  // namespace workspace
#line 11 "Library/src/number_theory/pow_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular exponentiation.
 *
 * @param __x
 * @param __n Exponent
 * @param __mod Modulus
 * @return
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> pow_mod(
    _Tp __x, _Tp __n, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  mul_type __y{1};

  while (__n) {
    if (__n & 1) (__y *= __x) %= __mod;
    __x = (mul_type)__x * __x % __mod;
    __n >>= 1;
  }

  return __y;
};

}  // namespace workspace
#line 10 "Library/src/number_theory/sqrt_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular square root.
 *
 * @param __x
 * @param __mod Modulus
 * @return One if it exists. Otherwise -1.
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> sqrt_mod(
    _Tp __x, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  if (!__x) return 0;

  if (__mod == 2) return __x;

  if (pow_mod(__x, __mod >> 1, __mod) != 1) return -1;

  _Tp __z = __builtin_ctz(__mod - 1), __q = __mod >> __z;

  mul_type __a = pow_mod(__x, (__q + 1) >> 1, __mod), __b = 2;
  while (pow_mod<_Tp>(__b, __mod >> 1, __mod) == 1) ++__b;
  __b = pow_mod<_Tp>(__b, __q, __mod);

  _Tp __shift = 0;

  for (auto __r = __a * __a % __mod * pow_mod(__x, __mod - 2, __mod) % __mod;
       __r != 1; (__r *= (__b *= __b) %= __mod) %= __mod) {
    auto __bsf = __z;

    for (auto __e = __r; __e != 1; --__bsf) (__e *= __e) %= __mod;

    while (++__shift != __bsf) (__b *= __b) %= __mod;

    (__a *= __b) %= __mod;
  }

  return __a;
};

}  // namespace workspace
#line 15 "Library/src/modular/modint.hpp"

namespace workspace {

namespace _modint_impl {

/**
 * @brief Modular arithmetic.
 *
 * @tparam Mod identifier, which represents modulus if positive
 * @tparam Storage Reserved size for inverse calculation
 */
template <auto Mod, unsigned Storage> struct modint {
  static_assert(is_integral_ext<decltype(Mod)>::value,
                "Mod must be integral type.");

  using mod_type = typename std::make_signed<typename std::conditional<
      0 < Mod, typename std::add_const<decltype(Mod)>::type,
      decltype(Mod)>::type>::type;

  using value_type = typename std::decay<mod_type>::type;

  using mul_type = typename multiplicable_uint<value_type>::type;

  // Modulus
  static mod_type mod;

  static unsigned storage;

  constexpr static void reserve(unsigned __n) noexcept { storage = __n; }

 private:
  value_type value = 0;

  struct direct_ctor_t {};
  constexpr static direct_ctor_t direct_ctor_tag{};

  // Direct constructor
  template <class _Tp> constexpr modint(_Tp __n, direct_ctor_t) : value(__n) {}

 public:
  constexpr modint() noexcept = default;

  template <class _Tp, typename std::enable_if<
                           is_integral_ext<_Tp>::value>::type * = nullptr>
  constexpr modint(_Tp __n) noexcept
      : value((__n %= mod) < 0 ? __n += mod : __n) {}

  constexpr modint(bool __n) noexcept : value(__n) {}

  constexpr operator value_type() const noexcept { return value; }

  constexpr static modint one() noexcept { return 1; }

  // unary operators {{
  constexpr modint operator++(int) noexcept {
    modint __t{*this};
    operator++();
    return __t;
  }

  constexpr modint operator--(int) noexcept {
    modint __t{*this};
    operator--();
    return __t;
  }

  constexpr modint &operator++() noexcept {
    if (++value == mod) value = 0;
    return *this;
  }

  constexpr modint &operator--() noexcept {
    if (!value)
      value = mod - 1;
    else
      --value;
    return *this;
  }

  constexpr modint operator+() const noexcept { return *this; }

  constexpr modint operator-() const noexcept {
    return {value ? mod - value : 0, direct_ctor_tag};
  }

  // }} unary operators

  // operator+= {{

  constexpr modint &operator+=(const modint &__x) noexcept {
    if ((value += __x.value) >= mod) value -= mod;
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator+=(_Tp const &__x) noexcept {
    if (((value += __x) %= mod) < 0) value += mod;
    return *this;
  }

  // }} operator+=

  // operator+ {{

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator+(_Tp const &__x) const noexcept {
    return modint{*this} += __x;
  }

  constexpr modint operator+(modint __x) const noexcept { return __x += *this; }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator+(_Tp const &__x, modint __y) noexcept {
    return __y += __x;
  }

  // }} operator+

  // operator-= {{

  constexpr modint &operator-=(const modint &__x) noexcept {
    if ((value -= __x.value) < 0) value += mod;
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator-=(_Tp __x) noexcept {
    if (((value -= __x) %= mod) < 0) value += mod;
    return *this;
  }

  // }} operator-=

  // operator- {{

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator-(_Tp const &__x) const noexcept {
    return modint{*this} -= __x;
  }

  constexpr modint operator-(const modint &__x) const noexcept {
    return modint{*this} -= __x;
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator-(_Tp __x, const modint &__y) noexcept {
    if (((__x -= __y.value) %= mod) < 0) __x += mod;
    return {__x, direct_ctor_tag};
  }

  // }} operator-

  // operator*= {{

  constexpr modint &operator*=(const modint &__x) noexcept {
    value =
        static_cast<value_type>(value * static_cast<mul_type>(__x.value) % mod);
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator*=(_Tp __x) noexcept {
    value = static_cast<value_type>(
        value * mul_type((__x %= mod) < 0 ? __x + mod : __x) % mod);
    return *this;
  }

  // }} operator*=

  // operator* {{

  constexpr modint operator*(const modint &__x) const noexcept {
    return {static_cast<mul_type>(value) * __x.value % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator*(_Tp __x) const noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(value) * __x % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator*(_Tp __x, const modint &__y) noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(__x) * __y.value % mod, direct_ctor_tag};
  }

  // }} operator*

 protected:
  static value_type _mem(value_type __x) {
    static std::vector<value_type> __m{0, 1};
    static value_type __i = (__m.reserve(Storage), 1);
    while (__i < __x) {
      ++__i;
      __m.emplace_back(mod - mul_type(mod / __i) * __m[mod % __i] % mod);
    }
    return __m[__x];
  }

  template <class _Tp>
  constexpr static
      typename std::enable_if<is_integral_ext<_Tp>::value, value_type>::type
      _div(mul_type __r, _Tp __x) noexcept {
    assert(__x != _Tp(0));
    if (!__r) return 0;

    std::make_signed_t<_Tp> __v{};
    bool __neg = __x < 0 ? __x = -__x, true : false;

    if (static_cast<decltype(storage)>(__x) < storage)
      __v = _mem(__x);
    else {
      decltype(__v) __y{mod}, __u{1}, __t;

      while (__x)
        __t = __y / __x, __y ^= __x ^= (__y -= __t * __x) ^= __x,
        __v ^= __u ^= (__v -= __t * __u) ^= __u;

      if (__y < 0) __neg ^= 1;
    }

    if (__neg)
      __v = 0 < __v ? mod - __v : -__v;
    else if (__v < 0)
      __v += mod;

    return __r == mul_type(1) ? static_cast<value_type>(__v)
                              : static_cast<value_type>(__r * __v % mod);
  }

 public:
  // operator/= {{

  constexpr modint &operator/=(const modint &__x) noexcept {
    if (value) value = _div(value, __x.value);
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator/=(_Tp __x) noexcept {
    if (value) value = _div(value, __x %= mod);
    return *this;
  }

  // }} operator/=

  // operator/ {{

  constexpr modint operator/(const modint &__x) const noexcept {
    if (!value) return {};
    return {_div(value, __x.value), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator/(_Tp __x) const noexcept {
    if (!value) return {};
    return {_div(value, __x %= mod), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator/(_Tp __x, const modint &__y) noexcept {
    if (!__x) return {};
    if ((__x %= mod) < 0) __x += mod;
    return {_div(__x, __y.value), direct_ctor_tag};
  }

  // }} operator/

  constexpr modint inv() const noexcept { return _div(1, value); }

  template <class _Tp>
  constexpr std::__enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      _Tp __e) const noexcept {
    modint __r{1, direct_ctor_tag};

    for (modint __b{__e < 0 ? __e = -__e, _div(1, value) : value,
                              direct_ctor_tag};
         __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  template <class _Tp>
  friend constexpr std::__enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      modint __b, _Tp __e) noexcept {
    if (__e < 0) {
      __e = -__e;
      __b.value = _div(1, __b.value);
    }

    modint __r{1, direct_ctor_tag};

    for (; __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  constexpr modint sqrt() const noexcept {
    return {sqrt_mod(value, mod), direct_ctor_tag};
  }

  friend constexpr modint sqrt(const modint &__x) noexcept {
    return {sqrt_mod(__x.value, mod), direct_ctor_tag};
  }

  template <class _Os>
  friend _Os &operator<<(_Os &__os, const modint &__x) noexcept {
    return __os << __x.value;
  }

  friend std::istream &operator>>(std::istream &__is, modint &__x) noexcept {
    std::string __s;
    __is >> __s;
    bool __neg = false;
    if (__s.front() == '-') {
      __neg = true;
      __s.erase(__s.begin());
    }
    __x = 0;
    for (char __c : __s) __x = __x * 10 + (__c - '0');
    if (__neg) __x = -__x;
    return __is;
  }
};

template <auto Mod, unsigned Storage>
typename modint<Mod, Storage>::mod_type modint<Mod, Storage>::mod =
    Mod > 0 ? Mod : 0;

template <auto Mod, unsigned Storage>
unsigned modint<Mod, Storage>::storage = Storage;

}  // namespace _modint_impl

/**
 * @brief Modular arithmetic.
 *
 * @tparam Mod modulus
 * @tparam Storage Reserved size for inverse calculation
 */
template <auto Mod, unsigned Storage = 0,
          typename std::enable_if<(Mod > 0)>::type * = nullptr>
using modint = _modint_impl::modint<Mod, Storage>;

/**
 * @brief Runtime modular arithmetic.
 *
 * @tparam type_id uniquely assigned
 * @tparam Storage Reserved size for inverse calculation
 */
template <unsigned type_id = 0, unsigned Storage = 0>
using modint_runtime = _modint_impl::modint<-(signed)type_id, Storage>;

// #define modint_newtype modint_runtime<__COUNTER__>

}  // namespace workspace
#line 31 "codeforces-workspace/contest/1511/f/f.cpp"

namespace workspace {

using mint = modint<998244353>;
using mat = matrix<mint>;

void main() {
  // start here!

  int n, k;
  cin >> n >> k;

  vector<string> wds(n), sufs{""};
  for (auto &&x : wds) {
    cin >> x;
    for (auto i : range(x.size())) {
      sufs.emplace_back(x.substr(i));
    }
  }

  sort(begin(sufs), end(sufs));
  sufs.erase(unique(begin(sufs), end(sufs)), end(sufs));

  const auto m = sufs.size();
  mat a(m * 5);

  for (auto i : range(4)) {
    for (auto j : range(m)) {
      a[i * m + j][(i + 1) * m + j] = 1;
    }
  }

  for (auto j : range(m)) {
    auto suf = sufs[j];
    for (auto w : wds) {
      if (w.substr(0, suf.size()) != suf || suf.size() == w.size()) {
        continue;
      }

      auto len = w.size() - suf.size();
      w = w.substr(suf.size());

      vector<mint> dp(w.size() + 1);
      dp[0] = 1;
      for (auto i : range(w.size())) {
        for (auto &&x : wds) {
          if (w.substr(i, x.size()) == x) dp[i + x.size()] += dp[i];
        }
      }
      for (auto i : range(w.size() + 1)) {
        auto cod = find(begin(sufs), end(sufs), w.substr(i));
        if (cod != sufs.end())
          a[(len - 1) * m + j][cod - sufs.begin()] += dp[i];
      }
    }
  }

  a = a.pow(k);
  cout << a[0][0] << "\n";
}

}  // namespace workspace

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PII pair<int,int>
const ll N=50 , INF=1e9 , mod=998244353 , Z=180;

int n,m;

int _a=0;
struct Matrix
{	ll M[Z][Z];

	ll* operator[](int i) {	  return M[i];	}

	Matrix operator *(const Matrix &B)
	{	static Matrix T1;
		memset( T1.M , 0 , sizeof T1);
		for(int i=0; i<_a; i++)
		for(int k=0; k<_a; k++)
		for(int j=0; j<_a; j++)
		T1.M[i][j]=(T1.M[i][j]+M[i][k]*B.M[k][j])%mod;
		return T1;
	}

	Matrix fmi(ll pow)
	{	static Matrix T2;
		Matrix B=*this;
		memset(T2.M,0,sizeof T2.M);
		for(int i=0; i<_a; i++) T2.M[i][i]=1;
		for(; pow; pow>>=1, B=B*B) if(pow&1) T2=T2*B;
		return T2;
	}
};

Matrix M0,M1,res;

	int ch[N][26];
	bool ed[N];
	int idx=0;

	void insert(char s[])
	{	int p=0;
		for(int i=0;s[i];i++)
		{	int c=s[i]-'a';
			if(!ch[p][c]) ch[p][c]=++idx;
			p=ch[p][c];
		}
		ed[p]=1;
	}

	int mp[3000],idn;
	bool ED[3000];

	inline int dfs(int u,int v)
	{	if(mp[u*N+v]) return mp[u*N+v];

		mp[u*N+v]=++idn;
		ED[idn]=(ed[u]&&ed[v]);
		int x=idn , su , sv ;

		for(int i=0;i<26;i++)
		{
			if(ch[u][i])
			{
				if(ch[v][i])
				{	su=ch[u][i] , sv=ch[v][i];
					M1.M[x][dfs(su,sv)]++;
				}
				if(ed[v]&&ch[0][i])
				{	su=ch[u][i] , sv=ch[0][i];
					M1.M[x][dfs(su,sv)]++;
				}
			}

			if(ed[u]&&ch[0][i])
			{	if(ch[v][i])
				{	su=ch[0][i] , sv=ch[v][i];
					M1.M[x][dfs(su,sv)]++;
				}
				if(ed[v]&&ch[0][i])
				{	su=ch[0][i] , sv=ch[0][i];
					M1.M[x][dfs(su,sv)]++;
				}
			}
		}
		return mp[u*N+v];
	}

	void solve()
	{	idn=0;
		///*
		for(int c=0;c<26;c++) if(ch[0][c]) dfs(ch[0][c],ch[0][c]);
		_a=idn+1;

		for(int c=0;c<26;c++) if(ch[0][c]) M0.M[0][mp[ch[0][c]*N+ch[0][c]]]++;
		//*/
		res=M0*M1.fmi(m-1);

		ll ans=0;
		for(int i=1;i<=idn;i++) if(ED[i]) ans=(ans+res.M[0][i])%mod;
		printf("%lld",ans);
	}

char s[10];
signed main()
{	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%s",s),insert(s);
	solve();
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PII pair<int,int>
const ll N=50 , INF=1e9 , mod=998244353 , Z=180;

int K=0,n,m;
/*
struct Matrix
{	ll M[Z][Z];
	Matrix(){memset(M,0,sizeof(M));}
	//ll* operator[](int i) {	  return M[i];	}

	Matrix operator *(const Matrix &B)
	{	Matrix T1;
		for(int i=0;i<K;i++)
		for(int j=0;j<K;j++)
		for(int k=0;k<K;k++)
		(T1.M[i][j]+=M[i][k]*B.M[k][j])%=mod;
		return T1;
	}

};
	Matrix fmi(Matrix G, ll pow)
	{
		Matrix T2;
		memset(T2.M,0,sizeof T2.M);
		for(int i=0;i<Z;i++) T2.M[i][i]=1;

		while(pow)
		{	if(pow&1) T2=T2*G;
			G=G*G;
			pow>>=1;
		}
		return T2;
	}
*/

struct Matrix{
	ll M[Z][Z];
	Matrix(){memset(M,0,sizeof(M));}
	Matrix operator*(const Matrix&a){
		Matrix r;
		for(int i=0;i<Z;i++)
			for(int k=0;k<Z;k++)
				for(int j=0;j<Z;j++)
					r.M[i][j]=(r.M[i][j]+M[i][k]*a.M[k][j])%mod;
		return r;
	}
};

Matrix fmi(Matrix a,ll b){
	Matrix res;
	for(int i=1;i<Z;i++)res.M[i][i]=1;
	for(;b;b>>=1){
		if(b&1)res=res*a;
		a=a*a;
	}
	return res;
}

Matrix M0,M1,res;

	int ch[N][26];
	bool ed[N];
	int idx=0;

	void insert(char s[])
	{	int p=0;
		for(int i=0;s[i];i++)
		{	int c=s[i]-'a';
			if(!ch[p][c]) ch[p][c]=++idx;
			p=ch[p][c];
		}
		ed[p]=1;
	}

	int mp[3000],idn;
	bool ED[3000];

	inline int dfs(int u,int v)
	{	if(mp[u*N+v]) return mp[u*N+v];

		mp[u*N+v]=++idn;
		ED[idn]=(ed[u]&&ed[v]);
		int x=idn , su , sv ;

		for(int i=0;i<26;i++)
		{
			if(ch[u][i])
			{
				if(ch[v][i])
				{	su=ch[u][i] , sv=ch[v][i];
					M1.M[x][dfs(su,sv)]++;
				}
				if(ed[v]&&ch[0][i])
				{	su=ch[u][i] , sv=ch[0][i];
					M1.M[x][dfs(su,sv)]++;
				}
			}

			if(ed[u]&&ch[0][i])
			{	if(ch[v][i])
				{	su=ch[0][i] , sv=ch[v][i];
					M1.M[x][dfs(su,sv)]++;
				}
				if(ed[v]&&ch[0][i])
				{	su=ch[0][i] , sv=ch[0][i];
					M1.M[x][dfs(su,sv)]++;
				}
			}
		}
		return mp[u*N+v];
	}

	void solve()
	{	idn=0;
		///*
		for(int c=0;c<26;c++) if(ch[0][c]) dfs(ch[0][c],ch[0][c]);
		K=idn+1;

		for(int c=0;c<26;c++) if(ch[0][c]) M0.M[0][mp[ch[0][c]*N+ch[0][c]]]++;
		//*/
		res=M0*fmi(M1,m-1);

		ll ans=0;
		for(int i=1;i<=idn;i++) if(ED[i]) ans=(ans+res.M[0][i])%mod;
		printf("%lld",ans);
	}

char s[10];
signed main()
{	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%s",s),insert(s);
	solve();
    return 0;
}

#include<bits/stdc++.h>
using namespace std;

const int maxn=505;
const int mod=998244353;
int n,m,tot,sz,rt;
char s[maxn];
int nxt[maxn][26],id[maxn][maxn];
bool ed[maxn];

class Matrix{
public:
	int m[maxn][maxn];
	Matrix operator*(const Matrix &o)const{
		Matrix res;
		for(int i=1;i<=sz;i++)for(int j=1;j<=sz;j++){
			res.m[i][j]=0;
			for(int k=1;k<=sz;k++)
				res.m[i][j]=(res.m[i][j]+1LL*m[i][k]*o.m[k][j])%mod;
		}
		return res;
	}
}trans;
Matrix power(Matrix x,int pow){
	Matrix res;
	for(int i=1;i<=sz;i++)for(int j=1;j<=sz;j++)
		res.m[i][j]=(i==j);
	for(;pow;pow>>=1){
		if(pow&1)res=res*x;
		x=x*x;
	}
	return res;
}

void insert(char *s){
	int len=strlen(s),cur=rt;
	for(int i=0;i<len;i++){
		if(!nxt[cur][s[i]-'a'])nxt[cur][s[i]-'a']=++tot;
		cur=nxt[cur][s[i]-'a'];
	}
	ed[cur]=true;
}
int getid(int cur1,int cur2){
	if(cur1>cur2)swap(cur1,cur2);
	if(id[cur1][cur2])return id[cur1][cur2];
	int cid=++sz;
	id[cur1][cur2]=cid;
	for(int c=0;c<26;c++)if(nxt[cur1][c]&&nxt[cur2][c]){
		int nxt1=nxt[cur1][c],nxt2=nxt[cur2][c];
		trans.m[cid][getid(nxt1,nxt2)]++;
		if(ed[nxt1])trans.m[cid][getid(rt,nxt2)]++;
		if(ed[nxt2])trans.m[cid][getid(nxt1,rt)]++;
		if(ed[nxt1]&&ed[nxt2])trans.m[cid][getid(rt,rt)]++;
	}
	return cid;
}

int main(){
	scanf("%d%d",&n,&m);
	rt=++tot;
	for(int i=1;i<=n;i++){
		scanf("%s",s+1);
		insert(s+1);
	}
	int ini=getid(rt,rt);
	trans=power(trans,m);
	printf("%d\n",trans.m[ini][ini]);
	return 0;
}

// #define _GLIBCXX_DEBUG // for STL debug (optional)
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
#include <bitset>
using namespace std;
using ll = long long int;
using int64 = long long int;

template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}

int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const int INF = 1LL << 29;
const ll LONGINF = 1LL << 60;
const ll MOD = 1000000007LL;

// 行列ライブラリ

// 演算子: 複合代入 (+=, -=), 単項 (-), 二項 (+, -, *, ==)
// eigen(N): N*N 単位行列を返す
// pow(mat, k): mat の k 乗を返す

template <typename T, int h, int w>
struct FixedMatrix {
    using array_type = array<T, h * w>;
    array_type mat;

    FixedMatrix(T val = T(0)) { mat.fill(val); }

    const inline T& at(int i, int j) const { return mat[i*w + j]; }
    inline T& at(int i, int j) { return mat[i*w + j]; }

    FixedMatrix<T, h, w> &operator+=(const FixedMatrix<T, h, w>& rhs) {
        for(size_t i=0; i<h; i++) {
            for(size_t j=0; j<w; j++) {
                this->at(i, j) += rhs.at(i, j);
            }
        }
        return *this;
    }

    FixedMatrix<T, h, w> operator-() const {
        FixedMatrix<T, h, w> res(*this);
        for(size_t i=0; i<h; i++) {
            for(size_t j=0; j<w; j++) {
                res.at(i, j) *= T(-1);
            }
        }
        return res;
    }

    FixedMatrix<T, h, w> &operator-=(const FixedMatrix<T, h, w>& rhs) {
        return (FixedMatrix<T, h, w>(*this) += -rhs);
    }

    template <int wr>
    FixedMatrix<T, h, wr> operator*(const FixedMatrix<T, w, wr>& rhs) {
        size_t H = h, W = wr, C = w;
        FixedMatrix<T, h, wr> res;
        for(size_t i=0; i<H; i++) {
            for(size_t j=0; j<W; j++) {
                for(size_t k=0; k<C; k++) {
                    res.at(i, j) += this->at(i, k) * rhs.at(k, j);
                }
            }
        }
        return res;
    }

    FixedMatrix<T, h, w> operator+(const FixedMatrix<T, h, w>& rhs) {
        return (FixedMatrix<T, h, w>(*this) += rhs);
    }

    FixedMatrix<T, h, w> operator-(const FixedMatrix<T, h, w> &rhs) {
        return (FixedMatrix<T, h, w>(*this) -= rhs);
    }

    bool operator==(const FixedMatrix<T, h, w> &rhs) const {
        return this->mat == rhs.mat;
    }
    bool operator!=(const FixedMatrix<T, h, w> &rhs) const {
        return !(*this == rhs);
    }
};

template <typename T, int h, int w>
FixedMatrix<T, h, w> eigen() {
    FixedMatrix<T, h, w> res(0);
    for(size_t i=0; i<h; i++) res.at(i, i) = T(1);
    return res;
}

template <typename T, int h, int w>
FixedMatrix<T, h, w> pow(FixedMatrix<T, h, w> mat, long long int k) {
    FixedMatrix<T, h, w> res = eigen<T, h, w>();
    for(; k>0; k>>=1) {
        if(k & 1) res = res * mat;
        mat = mat * mat;
    }
    return res;
}

template <typename T, int h, int w>
ostream& operator<< (ostream& out, FixedMatrix<T, h, w> mat) {
    int H = h, W = w;
    out << "[" << endl;
    for(int i=0; i<H; i++) {
        out << "  [ ";
        for(int j=0; j<W; j++) out << mat.at(i, j) << " ";
        out << "]" << endl;
    }
    out << "]" << endl;
    return out;
}

// ModInt begin

using ll = long long;
template<ll mod>
struct ModInt {
    ll v;
    ll mod_pow(ll x, ll n) const {
        return (!n) ? 1 : (mod_pow((x*x)%mod,n/2) * ((n&1)?x:1)) % mod;
    }
    ModInt(ll a = 0) : v((a %= mod) < 0 ? a + mod : a) {}
    ModInt operator+ ( const ModInt& b ) const {
        return (v + b.v >= mod ? ModInt(v + b.v - mod) : ModInt(v + b.v));
    }
    ModInt operator- () const {
        return ModInt(-v);
    }
    ModInt operator- ( const ModInt& b ) const {
        return (v - b.v < 0 ? ModInt(v - b.v + mod) : ModInt(v - b.v));
    }
    ModInt operator* ( const ModInt& b ) const {return (v * b.v) % mod;}
    ModInt operator/ ( const ModInt& b ) const {return (v * mod_pow(b.v, mod-2)) % mod;}

    bool operator== ( const ModInt &b ) const {return v == b.v;}
    bool operator!= ( const ModInt &b ) const {return !(*this == b); }
    ModInt& operator+= ( const ModInt &b ) {
        v += b.v;
        if(v >= mod) v -= mod;
        return *this;
    }
    ModInt& operator-= ( const ModInt &b ) {
        v -= b.v;
        if(v < 0) v += mod;
        return *this;
    }
    ModInt& operator*= ( const ModInt &b ) {
        (v *= b.v) %= mod;
        return *this;
    }
    ModInt& operator/= ( const ModInt &b ) {
        (v *= mod_pow(b.v, mod-2)) %= mod;
        return *this;
    }
    ModInt pow(ll x) { return ModInt(mod_pow(v, x)); }
    // operator int() const { return int(v); }
    // operator long long int() const { return v; }
};

template<ll mod>
ModInt<mod> pow(ModInt<mod> n, ll k) {
    return ModInt<mod>(n.mod_pow(n.v, k));
}

template<ll mod>
ostream& operator<< (ostream& out, ModInt<mod> a) {return out << a.v;}
template<ll mod>
istream& operator>> (istream& in, ModInt<mod>& a) {
    in >> a.v;
    return in;
}

// ModInt end

const int D = (8*5+1)*5;
using mint = ModInt<998244353>;
using Mat = FixedMatrix<mint, D, D>;

int main() {
    ll N, M; scanf("%lld%lld", &N, &M);
    vector<string> S(N);
    for(auto &e : S) cin >> e;

    vector<string> cand;
    cand.emplace_back("");
    {
        set<string> strs;
        for(int i=0; i<N; i++) {
            int len = S[i].size();
            for(int j=1; j<=len; j++) {
                strs.emplace(S[i].substr(len - j));
            }
        }
        for(auto e : strs) cand.emplace_back(e);
    }

    int X = cand.size();
    vector< vector< pair<int, int> > > adj(X);
    for(int i=0; i<X; i++) {
        if(cand[i] == "") {
            for(int j=0; j<N; j++) {
                for(int k=0; k<N; k++) {
                    int pre = 0;
                    while(pre < S[j].size() and pre < S[k].size()) {
                        if(S[j][pre] == S[k][pre])
                            pre++;
                        else
                            break;
                    }
                    int len = min(S[j].size(), S[k].size());
                    if(pre < len)
                        continue;

                    string s = "";
                    if(S[j].size() > S[k].size())
                        s = S[j].substr(pre);
                    else
                        s = S[k].substr(pre);
                    int f = -1;
                    for(int x=0; x<X; x++) {
                        if(s == cand[x]) {
                            f = x;
                            break;
                        }
                    }
                    assert(f >= 0);
                    adj[i].emplace_back(pre, f);
                }
            }
        }
        else {
            for(int j=0; j<N; j++) {
                int pre = 0;
                while(pre < S[j].size() and pre < cand[i].size()) {
                    if(S[j][pre] == cand[i][pre])
                        pre++;
                    else
                        break;
                }
                int len = min(S[j].size(), cand[i].size());
                if(pre < len)
                    continue;

                string s = "";
                if(S[j].size() > cand[i].size())
                    s = S[j].substr(pre);
                else
                    s = cand[i].substr(pre);
                int f = -1;
                for(int x=0; x<X; x++) {
                    if(s == cand[x]) {
                        f = x;
                        break;
                    }
                }
                assert(f >= 0);
                adj[i].emplace_back(pre, f);
            }
        }
    }

    // 行列を作る (adj[i][j] ・長さ k 追加 -> A[j][i] に足す)
    Mat mat;
    for(int i=0; i<X; i++) {
        for(auto e : adj[i]) {
            int len, j; tie(len, j) = e;
            mat.at(j, X*(len-1)+i) += mint(1);
        }
    }
    for(int i=0; i<4*X; i++) {
        mat.at(i+X, i) += mint(1);
    }

    Mat ans = pow(mat, M);
    cout << ans.at(0, 0) << endl;
    return 0;
}

// #define _GLIBCXX_DEBUG // for STL debug (optional)
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
#include <bitset>
using namespace std;
using ll = long long int;
using int64 = long long int;

template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}

int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const int INF = 1LL << 29;
const ll LONGINF = 1LL << 60;
const ll MOD = 1000000007LL;

// 行列ライブラリ

// 演算子: 複合代入 (+=, -=), 単項 (-), 二項 (+, -, *, ==)
// eigen(N): N*N 単位行列を返す
// pow(mat, k): mat の k 乗を返す

template <typename T, int h, int w>
struct FixedMatrix {
    using array_type = array<T, h * w>;
    array_type mat;

    FixedMatrix(T val = T(0)) { mat.fill(val); }

    const T& at(int i, int j) const { return mat[i*w + j]; }
    T& at(int i, int j) { return mat[i*w + j]; }

    FixedMatrix<T, h, w> &operator+=(const FixedMatrix<T, h, w>& rhs) {
        for(size_t i=0; i<h; i++) {
            for(size_t j=0; j<w; j++) {
                this->at(i, j) += rhs.at(i, j);
            }
        }
        return *this;
    }

    FixedMatrix<T, h, w> operator-() const {
        FixedMatrix<T, h, w> res(*this);
        for(size_t i=0; i<h; i++) {
            for(size_t j=0; j<w; j++) {
                res.at(i, j) *= T(-1);
            }
        }
        return res;
    }

    FixedMatrix<T, h, w> &operator-=(const FixedMatrix<T, h, w>& rhs) {
        return (FixedMatrix<T, h, w>(*this) += -rhs);
    }

    template <int wr>
    FixedMatrix<T, h, wr> operator*(const FixedMatrix<T, w, wr>& rhs) {
        size_t H = h, W = wr, C = w;
        FixedMatrix<T, h, wr> res;
        for(size_t i=0; i<H; i++) {
            for(size_t j=0; j<W; j++) {
                for(size_t k=0; k<C; k++) {
                    res.at(i, j) += this->at(i, k) * rhs.at(k, j);
                }
            }
        }
        return res;
    }

    FixedMatrix<T, h, w> operator+(const FixedMatrix<T, h, w>& rhs) {
        return (FixedMatrix<T, h, w>(*this) += rhs);
    }

    FixedMatrix<T, h, w> operator-(const FixedMatrix<T, h, w> &rhs) {
        return (FixedMatrix<T, h, w>(*this) -= rhs);
    }

    bool operator==(const FixedMatrix<T, h, w> &rhs) const {
        return this->mat == rhs.mat;
    }
    bool operator!=(const FixedMatrix<T, h, w> &rhs) const {
        return !(*this == rhs);
    }
};

template <typename T, int h, int w>
FixedMatrix<T, h, w> eigen() {
    FixedMatrix<T, h, w> res(0);
    for(size_t i=0; i<h; i++) res.at(i, i) = T(1);
    return res;
}

template <typename T, int h, int w>
FixedMatrix<T, h, w> pow(FixedMatrix<T, h, w> mat, long long int k) {
    FixedMatrix<T, h, w> res = eigen<T, h, w>();
    for(; k>0; k>>=1) {
        if(k & 1) res = res * mat;
        mat = mat * mat;
    }
    return res;
}

template <typename T, int h, int w>
ostream& operator<< (ostream& out, FixedMatrix<T, h, w> mat) {
    int H = h, W = w;
    out << "[" << endl;
    for(int i=0; i<H; i++) {
        out << "  [ ";
        for(int j=0; j<W; j++) out << mat.at(i, j) << " ";
        out << "]" << endl;
    }
    out << "]" << endl;
    return out;
}

// ModInt begin

using ll = long long;
template<ll mod>
struct ModInt {
    ll v;
    ll mod_pow(ll x, ll n) const {
        return (!n) ? 1 : (mod_pow((x*x)%mod,n/2) * ((n&1)?x:1)) % mod;
    }
    ModInt(ll a = 0) : v((a %= mod) < 0 ? a + mod : a) {}
    ModInt operator+ ( const ModInt& b ) const {
        return (v + b.v >= mod ? ModInt(v + b.v - mod) : ModInt(v + b.v));
    }
    ModInt operator- () const {
        return ModInt(-v);
    }
    ModInt operator- ( const ModInt& b ) const {
        return (v - b.v < 0 ? ModInt(v - b.v + mod) : ModInt(v - b.v));
    }
    ModInt operator* ( const ModInt& b ) const {return (v * b.v) % mod;}
    ModInt operator/ ( const ModInt& b ) const {return (v * mod_pow(b.v, mod-2)) % mod;}

    bool operator== ( const ModInt &b ) const {return v == b.v;}
    bool operator!= ( const ModInt &b ) const {return !(*this == b); }
    ModInt& operator+= ( const ModInt &b ) {
        v += b.v;
        if(v >= mod) v -= mod;
        return *this;
    }
    ModInt& operator-= ( const ModInt &b ) {
        v -= b.v;
        if(v < 0) v += mod;
        return *this;
    }
    ModInt& operator*= ( const ModInt &b ) {
        (v *= b.v) %= mod;
        return *this;
    }
    ModInt& operator/= ( const ModInt &b ) {
        (v *= mod_pow(b.v, mod-2)) %= mod;
        return *this;
    }
    ModInt pow(ll x) { return ModInt(mod_pow(v, x)); }
    // operator int() const { return int(v); }
    // operator long long int() const { return v; }
};

template<ll mod>
ModInt<mod> pow(ModInt<mod> n, ll k) {
    return ModInt<mod>(n.mod_pow(n.v, k));
}

template<ll mod>
ostream& operator<< (ostream& out, ModInt<mod> a) {return out << a.v;}
template<ll mod>
istream& operator>> (istream& in, ModInt<mod>& a) {
    in >> a.v;
    return in;
}

// ModInt end

const int D = (8*5+1)*5;
using mint = ModInt<998244353>;
using Mat = FixedMatrix<mint, D, D>;

int main() {
    ll N, M; scanf("%lld%lld", &N, &M);
    vector<string> S(N);
    for(auto &e : S) cin >> e;

    vector<string> cand;
    cand.emplace_back("");
    {
        set<string> strs;
        for(int i=0; i<N; i++) {
            int len = S[i].size();
            for(int j=1; j<=len; j++) {
                strs.emplace(S[i].substr(len - j));
            }
        }
        for(auto e : strs) cand.emplace_back(e);
    }

    int X = cand.size();
    vector< vector< pair<int, int> > > adj(X);
    for(int i=0; i<X; i++) {
        if(cand[i] == "") {
            for(int j=0; j<N; j++) {
                for(int k=0; k<N; k++) {
                    int pre = 0;
                    while(pre < S[j].size() and pre < S[k].size()) {
                        if(S[j][pre] == S[k][pre])
                            pre++;
                        else
                            break;
                    }
                    int len = min(S[j].size(), S[k].size());
                    if(pre < len)
                        continue;

                    string s = "";
                    if(S[j].size() > S[k].size())
                        s = S[j].substr(pre);
                    else
                        s = S[k].substr(pre);
                    int f = -1;
                    for(int x=0; x<X; x++) {
                        if(s == cand[x]) {
                            f = x;
                            break;
                        }
                    }
                    assert(f >= 0);
                    adj[i].emplace_back(pre, f);
                }
            }
        }
        else {
            for(int j=0; j<N; j++) {
                int pre = 0;
                while(pre < S[j].size() and pre < cand[i].size()) {
                    if(S[j][pre] == cand[i][pre])
                        pre++;
                    else
                        break;
                }
                int len = min(S[j].size(), cand[i].size());
                if(pre < len)
                    continue;

                string s = "";
                if(S[j].size() > cand[i].size())
                    s = S[j].substr(pre);
                else
                    s = cand[i].substr(pre);
                int f = -1;
                for(int x=0; x<X; x++) {
                    if(s == cand[x]) {
                        f = x;
                        break;
                    }
                }
                assert(f >= 0);
                adj[i].emplace_back(pre, f);
            }
        }
    }

    // 行列を作る (adj[i][j] ・長さ k 追加 -> A[j][i] に足す)
    Mat mat;
    for(int i=0; i<X; i++) {
        for(auto e : adj[i]) {
            int len, j; tie(len, j) = e;
            mat.at(j, X*(len-1)+i) += mint(1);
        }
    }
    for(int i=0; i<4*X; i++) {
        mat.at(i+X, i) += mint(1);
    }

    Mat ans = pow(mat, M);
    cout << ans.at(0, 0) << endl;
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int mod = 998244353;

int son[50][26], bck[50], TOT = 1;
int A[210][210], N, ans[210][210], tmp[210][210];

void dfs(int x, int y, int d, int id) {
	if (d == 0) {
		if (bck[x]) A[id][y * 5]++;
		if (bck[y]) A[id][x * 5]++;
		if (bck[x] && bck[y]) A[id][0]++;
		return ;
	}
	for (int i = 0; i < 26; i++) {
		if (son[x][i] != -1 && son[y][i] != -1) dfs(son[x][i], son[y][i], d - 1, id);
	}
}

int main() {
	memset(son, -1, sizeof(son));
	int n, m; scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++) {
		string s; cin >> s;
		int now = 0;
		for (auto x : s) now = ~son[now][x - 'a'] ? son[now][x - 'a'] : son[now][x - 'a'] = TOT++;
		bck[now] = 1;
	}
	N = TOT * 5;
	for (int i = 0; i < TOT; i++) {
		for (int j = 0; j < 5; j++) {
			if (j < 4) A[i * 5 + j][i * 5 + j + 1]++;
			dfs(0, i, j + 1, i * 5 + j);
		}
	}
	for (int i = 0; i < N; i++) ans[i][i] = 1;
	for (int it = 0; it < 30; it++) {
		if (m >> it & 1) {
			memset(tmp, 0, sizeof(tmp));
			for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) for (int k = 0; k < N; k++) {
				tmp[i][j] = (tmp[i][j] + 1ll * A[i][k] * ans[k][j]) % mod;
			}
			memcpy(ans, tmp, sizeof(tmp));
		}
		memset(tmp, 0, sizeof(tmp));
		for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) for (int k = 0; k < N; k++) {
			tmp[i][j] = (tmp[i][j] + 1ll * A[i][k] * A[k][j]) % mod;
		}
		memcpy(A, tmp, sizeof(tmp));
	}
	printf("%d\n", ans[0][0]);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;

#define int long long

const int N=1e3+1e1+7,P=998244353;

void inc(int &a,int b)
{
	a+=b;
	a>=P?a-=P:0;
}

int k;

struct Matrix{
	int a[N][N];

	void init()
	{
		for(int i=0;i<=k;i++)
			a[i][i]=1;
	}

	void clear()
	{
		for(int i=0;i<=k;i++)
			for(int j=0;j<=k;j++)
				a[i][j]=0;
	}
}A,B;

Matrix operator *(const Matrix &a,const Matrix &b)
{
	Matrix ret;
	ret.clear();
	for(int i=0;i<=k;i++)
		for(int j=0;j<=k;j++)
			for(int t=0;t<=k;t++)
				inc(ret.a[i][j],a.a[i][t]*b.a[t][j]%P);
	return ret;
}

Matrix qpow(Matrix &a,int b)
{
	Matrix ret;
	ret.clear();
	ret.init();
	while(b)
	{
		if(b&1)
			ret=ret*a;
		b>>=1;
		a=a*a;
	}
	return ret;
}

int trie[N][26],tot,tag[N];

void insert(char *s)
{
	int x=0,len=strlen(s);
	for(int i=0;i<len;i++)
	{
		if(trie[x][s[i]-'a']==-1)
		{
			trie[x][s[i]-'a']=++tot;
			for(int j=0;j<26;j++)
				trie[tot][j]=-1;
		}
		x=trie[x][s[i]-'a'];
	}
	tag[x]=1;
}

char s[11];

int n,m;

typedef pair<int,int> pii;
#define fs first
#define sd second
#define mp make_pair

map<pii,int>id;

pii pos[N];

int getid(int x,int y)
{
	if(x>y)
		swap(x,y);
	if(id.find(mp(x,y))==id.end())
		id[mp(x,y)]=++k,pos[k]=mp(x,y);
	return id[mp(x,y)];
}

queue<int>q;

map<int,int>vis;

signed main()
{
	for(int i=0;i<26;i++)
		trie[0][i]=-1;
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%s",s),insert(s);
	id[mp(0,0)]=0;
	q.push(0);
	A.a[0][0]=1;
	while(!q.empty())
	{
		int p=q.front();
		q.pop();
		if(vis[p])
			continue;
		vis[p]=1;
		int x=pos[p].fs,y=pos[p].sd;
		for(int i=0;i<26;i++)
		{
			int tx=trie[x][i],ty=trie[y][i];
			if(tx==-1||ty==-1)
				continue;
			int tp=getid(tx,ty);
			q.push(tp);
			B.a[p][tp]++;
			if(tag[tx])
				B.a[p][getid(0,ty)]++,q.push(getid(0,ty));
			if(tag[ty])
				B.a[p][getid(tx,0)]++,q.push(getid(tx,0));
			if(tag[tx]&&tag[ty])
				B.a[p][getid(0,0)]++;
		}
	}
	A=A*qpow(B,m);
	printf("%lld\n",A.a[0][0]);
}

#include<bits/stdc++.h>
using namespace std;

#define int long long

const int N=5e2+1e1+7,P=998244353;

void inc(int &a,int b)
{
	a+=b;
	a>=P?a-=P:0;
}

int k;

struct Matrix{
	int a[N][N];

	void init()
	{
		for(int i=0;i<=k;i++)
			a[i][i]=1;
	}

	void clear()
	{
		for(int i=0;i<=k;i++)
			for(int j=0;j<=k;j++)
				a[i][j]=0;
	}
}A,B;

Matrix operator *(const Matrix &a,const Matrix &b)
{
	Matrix ret;
	ret.clear();
	for(int i=0;i<=k;i++)
		for(int j=0;j<=k;j++)
			for(int t=0;t<=k;t++)
				inc(ret.a[i][j],a.a[i][t]*b.a[t][j]%P);
	return ret;
}

Matrix qpow(Matrix &a,int b)
{
	Matrix ret;
	ret.clear();
	ret.init();
	while(b)
	{
		if(b&1)
			ret=ret*a;
		b>>=1;
		a=a*a;
	}
	return ret;
}

int trie[N][26],tot,tag[N];

void insert(char *s)
{
	int x=0,len=strlen(s);
	for(int i=0;i<len;i++)
	{
		if(trie[x][s[i]-'a']==-1)
		{
			trie[x][s[i]-'a']=++tot;
			for(int j=0;j<26;j++)
				trie[tot][j]=-1;
		}
		x=trie[x][s[i]-'a'];
	}
	tag[x]=1;
}

char s[11];

int n,m;

typedef pair<int,int> pii;
#define fs first
#define sd second
#define mp make_pair

map<pii,int>id;

pii pos[N];

int getid(int x,int y)
{
	if(x>y)
		swap(x,y);
	if(id.find(mp(x,y))==id.end())
		id[mp(x,y)]=++k,pos[k]=mp(x,y);
	return id[mp(x,y)];
}

queue<int>q;

map<int,int>vis;

signed main()
{
	for(int i=0;i<26;i++)
		trie[0][i]=-1;
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%s",s),insert(s);
	id[mp(0,0)]=0;
	q.push(0);
	A.a[0][0]=1;
	while(!q.empty())
	{
		int p=q.front();
		q.pop();
		if(vis[p])
			continue;
		vis[p]=1;
		int x=pos[p].fs,y=pos[p].sd;
		for(int i=0;i<26;i++)
		{
			int tx=trie[x][i],ty=trie[y][i];
			if(tx==-1||ty==-1)
				continue;
			int tp=getid(tx,ty);
			q.push(tp);
			B.a[p][tp]++;
			if(tag[tx])
				B.a[p][getid(0,ty)]++,q.push(getid(0,ty));
			if(tag[ty])
				B.a[p][getid(tx,0)]++,q.push(getid(tx,0));
			if(tag[tx]&&tag[ty])
				B.a[p][getid(0,0)]++;
		}
	}
	A=A*qpow(B,m);
	printf("%lld\n",A.a[0][0]);
}

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=248,p=998244353;
int n,m,k,d[N][N],s[N][26];
bool pd[N];
char ch;
struct mtx{
	int a[N][N];
	inline mtx operator *(const mtx &v)const{
		mtx w;memset(w.a,0,sizeof w.a);
		for(int i=0;i<k;i++) for(int j=0;j<k;j++) if(a[i][j])
			for(int l=0;l<k;l++) w.a[i][l]=(w.a[i][l]+(ll)a[i][j]*v.a[j][l])%p;
		return w;
	}
}x,y;
int dfs(int u,int v){
	if(u>v) swap(u,v);
	if(d[u][v]>=0) return d[u][v];
	int o=d[u][v]=k++;
	for(int i=0,_u,_v;i<26;i++){
		_u=s[u][i];_v=s[v][i];
		if(!_u||!_v) continue;
		x.a[o][dfs(_u,_v)]++;
		if(pd[_u]) x.a[o][dfs(0,_v)]++;
		if(pd[_v]) x.a[o][dfs(_u,0)]++;
		if(pd[_u]&&pd[_v]) x.a[o][0]++;
	}
	return o;
}
int main(){
	cin>>n>>m;memset(d,-1,sizeof d);
	for(int i=1,u=0,v;i<=n;i++){
		scanf("\n");ch=getchar();
		while(ch>='a'&&ch<='z'){
			v=ch-'a';
			if(!s[u][v]) s[u][v]=++k;
			u=s[u][v];ch=getchar();
		}
		pd[u]=1;u=0;
	}
	k=0;dfs(0,0);y=x;m--;
	while(m){
		if(m&1) y=y*x;
		m>>=1;x=x*x;
	}
	cout<<y.a[0][0];
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 300;
const int mod = 998244353;
int num;
struct matrix{
	ll a[N][N];
	matrix(){
		memset(a,0,sizeof(a));
	}
	void init(){
		for(int i=0;i<num;i++) a[i][i] = 1;
	}
	matrix operator * (matrix B){
		matrix C;
		for(int i=0;i<num;i++) for(int j=0;j<num;j++){
			for(int k=0;k<num;k++){
				C.a[i][j] += a[i][k] * B.a[k][j] % mod;
			}
			C.a[i][j] %= mod;
		}
		return C;
	}
	matrix operator ^ (ll k){
		matrix res, A = (*this);
		res.init();
		while(k){
			if(k&1) res = res * A;
			A = A * A;
			k >>= 1;
		}
		return res;
	}
};
int t[N][30], sz = 1, cnt[N];
int main(){
	ios::sync_with_stdio(0);
	int n,m; cin>>n>>m;
	while(n--){
		string s; cin>>s;
		int u = 0;
		for(char c: s){
			int &v = t[u][c-'a'];
			if(!v) v = sz++;
			u = v;
		}
		cnt[u] = 1;
	}
	matrix A;
	typedef array<int,2> P;
	map<P,int> vis, idmap;
	function<int(P)> id = [&](P p){
		if(idmap.count(p)) return idmap[p];
		return idmap[p] = num++;
	};
	queue<P> q; q.push({0,0}); id({0,0}); vis[{0,0}] = 1;
	while(!q.empty()){
		auto [i,j] = q.front(); q.pop();
		for(int x=0;x<26;x++) if(t[i][x]&&t[j][x]){
			int ti = t[i][x], tj = t[j][x];
			vector<int> a,b;
			if(cnt[ti]) a.push_back(0);
			for(int k=0;k<26;k++) if(t[ti][k]){
				a.push_back(ti); break;
			}
			if(cnt[tj]) b.push_back(0);
			for(int k=0;k<26;k++) if(t[tj][k]){
				b.push_back(tj); break;
			}
			for(int ti: a) for(int tj: b){
				A.a[id({i,j})][id({ti,tj})]++;
				if(!vis[{ti,tj}]){
					vis[{ti,tj}] = 1;
					q.push({ti,tj});
				}
			}
		}
	}
	A = A ^ m;
	cout<<A.a[0][0]<<endl;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <iomanip>
#define endl '\n'
#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ldb;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef pair<LL, int> pli;
typedef pair<int, long> pil;
const int INF = 0x3f3f3f3f;
inline int read(){
    register int x; register char c(getchar()); register bool k;
    while((c < '0' || c > '9') && c ^ '-') if((c = getchar()) == EOF) exit(0);
    if(c ^ '-') x = c & 15, k = 1; else x = 0, k = 0;
    while(c = getchar(), c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c & 15);
    return k ? x : -x;
}

const int maxn = 100, mod = 998244353;
char s[10];
int trie[maxn][26], tot;
bool endp[maxn];

void insert(char *s){
    int len = strlen(s), cur = 0;
    for(int i = 0; i < len; i++){
        if(!trie[cur][s[i] - 'a']) trie[cur][s[i] - 'a'] = ++tot;
        cur = trie[cur][s[i] - 'a'];
    }
    endp[cur] = 1;
}

typedef vector<int> vec;
typedef vector<vec> mat;

// 计算矩阵A*矩阵B，元素对mod取模
mat mod_mul(mat &A, mat &B){
    mat C(A.size(), vec(B[0].size()));
    for(int i = 0; i < A.size(); i++){
        for(int k = 0; k < B.size(); k++){
            if(A[i][k])
            for(int j = 0; j < B[0].size(); j++){
                if(B[k][j])
                C[i][j] = (C[i][j] + ((LL)A[i][k] * B[k][j]) % mod) % mod;
            }
        }
    }
    return C;
}

// 计算矩阵A的n次方
mat mod_pow(mat A, LL n){
    mat B(A.size(), vec(A.size()));
    for(int i =0; i < A.size(); i++) B[i][i] = 1;
    while(n > 0){
        if(n & 1) B = mod_mul(B, A);
        A = mod_mul(A, A);
        n >>= 1;
    }
    return B;
}

queue<pii> que;
map<pii, int> mp;
int cnt;
int get_id(pii p){
    if(mp.count(p)) return mp[p];
    mp[p] = cnt++;
    que.push(p);
    return cnt - 1;
}

int main(){
    int n = read(), m = read();
    for(int i = 1; i <= n; i++){
        scanf("%s", s);
        insert(s);
    }
    mat M = mat(200, vec(200));
    get_id(pii(0, 0));
    while(que.size()){
        pii p = que.front(); que.pop();
        int p1 = p.first, p2 = p.second, id = get_id(p);
        for(int i = 0; i < 26; i++){
            int tp1 = trie[p1][i], tp2 = trie[p2][i];
            if(!tp1 || !tp2) continue;
            M[id][get_id(pii(tp1, tp2))]++;
            if(endp[tp1]) M[id][get_id(pii(0, tp2))]++;
            if(endp[tp2]) M[id][get_id(pii(0,tp1))]++;
            if(endp[tp1] && endp[tp2]) M[id][get_id(pii(0, 0))]++;
        }
    }
    /*for(int i = 0; i < 15; i++){
        for(int j = 0; j < 15; j++)
            cout << M[i][j] << ' ';
        cout << endl;
    }*/
    mat ans = mod_pow(M, m);
    cout << ans[0][0] << endl;
    return 0;
}

//JZM yyds!!
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#define ll long long
#define MAXN 10005
#define uns unsigned
#define INF 0x3f3f3f3f
#define MOD 998244353ll
#define lowbit(x) ((x)&(-(x)))
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return f?x:-x;
}
struct matrix{
	int n,m;
	ll c[205][205];
	matrix(){memset(c,0,sizeof(c)),n=m=0;}
	matrix operator*(const matrix&a){
		matrix r;r.n=n,r.m=a.m;
		for(int i=1;i<=r.n;i++)
			for(int k=1;k<=m;k++)
				for(int j=1;j<=r.m;j++)
					r.c[i][j]=(r.c[i][j]+c[i][k]*a.c[k][j])%MOD;
		return r;
	}
};
matrix mpow(matrix a,ll b){
	matrix res;res.n=res.m=a.n;
	for(int i=1;i<=res.n;i++)res.c[i][i]=1;
	for(;b;b>>=1){
		if(b&1)res=res*a;
		a=a*a;
	}
	return res;
}
int n,m,t[50][30],mp[MAXN],IN,k;
bool op[50],ct[MAXN];
matrix a,b;
inline void instr(){
	int p=0,c;
	char s=getchar();
	while((s<'a'||s>'z')&&s>0)s=getchar();
	while(s>='a'&&s<='z'){
		c=s-'a';
		if(!t[p][c])t[p][c]=++IN;
		p=t[p][c],s=getchar();
	}
	op[p]=1;
}
inline int dfs(int u,int v){
	if(mp[u*100+v]>0)return mp[u*100+v];
	mp[u*100+v]=++b.n,b.m++,ct[b.n]=(op[u]&op[v]);
	int x=mp[u*100+v],y,c,d;
	for(int i=0;i<26;i++){
		if(op[u]&&t[0][i]){
			if(op[v]){
				c=t[0][i],d=t[0][i];
				y=dfs(c,d);
				b.c[x][y]=1;
			}
			if(t[v][i]){
				c=t[0][i],d=t[v][i];
				y=dfs(c,d),b.c[x][y]=1;
			}
		}
		if(t[u][i]){
			if(op[v]&&t[0][i]){
				c=t[u][i],d=t[0][i];
				y=dfs(c,d),b.c[x][y]=1;
			}
			if(t[v][i]){
				c=t[u][i],d=t[v][i];
				y=dfs(c,d),b.c[x][y]=1;
			}
		}
	}
	return x;
}
signed main()
{
	n=read(),m=read();
	for(int i=1;i<=n;i++)instr();
	for(int i=0;i<26;i++)if(t[0][i])dfs(t[0][i],t[0][i]);
	a.n=1,a.m=b.n;
	for(int i=0;i<26;i++)
		if(t[0][i]){
			int u=t[0][i],x=mp[u*100+u];
			a.c[1][x]=1;
		}
	a=a*mpow(b,m-1);
	ll ans=0;
	for(int i=1;i<=a.m;i++)if(ct[i])ans=(ans+a.c[1][i])%MOD;
	printf("%lld\n",ans);
 //   system("pause");
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
using namespace chrono;
mt19937 rng(high_resolution_clock::now().time_since_epoch().count());
mt19937_64 rngll(high_resolution_clock::now().time_since_epoch().count());

template<typename T>
struct Z_p{
	using Type = typename decay<decltype(T::value)>::type;
	static vector<Type> MOD_INV;
	constexpr Z_p(): value(){ }
	template<typename U> Z_p(const U &x){ value = normalize(x); }
	template<typename U> static Type normalize(const U &x){
		Type v;
		if(-mod() <= x && x < mod()) v = static_cast<Type>(x);
		else v = static_cast<Type>(x % mod());
		if(v < 0) v += mod();
		return v;
	}
	const Type& operator()() const{ return value; }
	template<typename U> explicit operator U() const{ return static_cast<U>(value); }
	constexpr static Type mod(){ return T::value; }
	Z_p &operator+=(const Z_p &otr){ if((value += otr.value) >= mod()) value -= mod(); return *this; }
	Z_p &operator-=(const Z_p &otr){ if((value -= otr.value) < 0) value += mod(); return *this; }
	template<typename U> Z_p &operator+=(const U &otr){ return *this += Z_p(otr); }
	template<typename U> Z_p &operator-=(const U &otr){ return *this -= Z_p(otr); }
	Z_p &operator++(){ return *this += 1; }
	Z_p &operator--(){ return *this -= 1; }
	Z_p operator++(int){ Z_p result(*this); *this += 1; return result; }
	Z_p operator--(int){ Z_p result(*this); *this -= 1; return result; }
	Z_p operator-() const{ return Z_p(-value); }
	template<typename U = T>
	typename enable_if<is_same<typename Z_p<U>::Type, int>::value, Z_p>::type &operator*=(const Z_p& rhs){
		#ifdef _WIN32
		uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value);
		uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x), d, m;
		asm(
			"divl %4; \n\t"
			: "=a" (d), "=d" (m)
			: "d" (xh), "a" (xl), "r" (mod())
		);
		value = m;
		#else
		value = normalize(static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value));
		#endif
		return *this;
	}
	template<typename U = T>
	typename enable_if<is_same<typename Z_p<U>::Type, int64_t>::value, Z_p>::type &operator*=(const Z_p &rhs){
		int64_t q = static_cast<int64_t>(static_cast<long double>(value) * rhs.value / mod());
		value = normalize(value * rhs.value - q * mod());
		return *this;
	}
	template<typename U = T>
	typename enable_if<!is_integral<typename Z_p<U>::Type>::value, Z_p>::type &operator*=(const Z_p &rhs){
		value = normalize(value * rhs.value);
		return *this;
	}
	template<typename U>
	Z_p &operator^=(U e){
		if(e < 0) *this = 1 / *this, e = -e;
		Z_p res = 1;
		for(; e; *this *= *this, e >>= 1) if(e & 1) res *= *this;
		return *this = res;
	}
	template<typename U>
	Z_p operator^(U e) const{
		return Z_p(*this) ^= e;
	}
	Z_p &operator/=(const Z_p &otr){
		Type a = otr.value, m = mod(), u = 0, v = 1;
		if(a < (int)MOD_INV.size()) return *this *= MOD_INV[a];
		while(a){
			Type t = m / a;
			m -= t * a; swap(a, m);
			u -= t * v; swap(u, v);
		}
		assert(m == 1);
		return *this *= u;
	}
	template<typename U> friend const Z_p<U> &abs(const Z_p<U> &v){ return v; }
	Type value;
};
template<typename T> bool operator==(const Z_p<T> &lhs, const Z_p<T> &rhs){ return lhs.value == rhs.value; }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> bool operator==(const Z_p<T>& lhs, U rhs){ return lhs == Z_p<T>(rhs); }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> bool operator==(U lhs, const Z_p<T> &rhs){ return Z_p<T>(lhs) == rhs; }
template<typename T> bool operator!=(const Z_p<T> &lhs, const Z_p<T> &rhs){ return !(lhs == rhs); }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> bool operator!=(const Z_p<T> &lhs, U rhs){ return !(lhs == rhs); }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> bool operator!=(U lhs, const Z_p<T> &rhs){ return !(lhs == rhs); }
template<typename T> bool operator<(const Z_p<T> &lhs, const Z_p<T> &rhs){ return lhs.value < rhs.value; }
template<typename T> bool operator>(const Z_p<T> &lhs, const Z_p<T> &rhs){ return lhs.value > rhs.value; }
template<typename T> bool operator<=(const Z_p<T> &lhs, const Z_p<T> &rhs){ return lhs.value <= rhs.value; }
template<typename T> bool operator>=(const Z_p<T> &lhs, const Z_p<T> &rhs){ return lhs.value >= rhs.value; }
template<typename T> Z_p<T> operator+(const Z_p<T> &lhs, const Z_p<T> &rhs){ return Z_p<T>(lhs) += rhs; }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> Z_p<T> operator+(const Z_p<T> &lhs, U rhs){ return Z_p<T>(lhs) += rhs; }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> Z_p<T> operator+(U lhs, const Z_p<T> &rhs){ return Z_p<T>(lhs) += rhs; }
template<typename T> Z_p<T> operator-(const Z_p<T> &lhs, const Z_p<T> &rhs){ return Z_p<T>(lhs) -= rhs; }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> Z_p<T> operator-(const Z_p<T>& lhs, U rhs){ return Z_p<T>(lhs) -= rhs; }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> Z_p<T> operator-(U lhs, const Z_p<T> &rhs){ return Z_p<T>(lhs) -= rhs; }
template<typename T> Z_p<T> operator*(const Z_p<T> &lhs, const Z_p<T> &rhs){ return Z_p<T>(lhs) *= rhs; }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> Z_p<T> operator*(const Z_p<T>& lhs, U rhs){ return Z_p<T>(lhs) *= rhs; }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> Z_p<T> operator*(U lhs, const Z_p<T> &rhs){ return Z_p<T>(lhs) *= rhs; }
template<typename T> Z_p<T> operator/(const Z_p<T> &lhs, const Z_p<T> &rhs) { return Z_p<T>(lhs) /= rhs; }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> Z_p<T> operator/(const Z_p<T>& lhs, U rhs) { return Z_p<T>(lhs) /= rhs; }
template<typename T, typename U, typename enable_if<is_integral<U>::value>::type* = nullptr> Z_p<T> operator/(U lhs, const Z_p<T> &rhs) { return Z_p<T>(lhs) /= rhs; }
template<typename T> istream &operator>>(istream &in, Z_p<T> &number){
	typename common_type<typename Z_p<T>::Type, int64_t>::type x;
	in >> x;
	number.value = Z_p<T>::normalize(x);
	return in;
}
template<typename T> ostream &operator<<(ostream &out, const Z_p<T> &number){ return out << number(); }

/*
using ModType = int;
struct VarMod{ static ModType value; };
ModType VarMod::value;
ModType &mod = VarMod::value;
using Zp = Z_p<VarMod>;
*/

// constexpr int mod = 1e9 + 7; // 1000000007
constexpr int mod = (119 << 23) + 1; // 998244353
// constexpr int mod = 1e9 + 9; // 1000000009
using Zp = Z_p<integral_constant<decay<decltype(mod)>::type, mod>>;

template<typename T> vector<typename Z_p<T>::Type> Z_p<T>::MOD_INV;
template<typename T = integral_constant<decay<decltype(mod)>::type, mod>>
void precalc_inverse(int SZ){
	auto &inv = Z_p<T>::MOD_INV;
	if(inv.empty()) inv.assign(2, 1);
	for(; inv.size() <= SZ; ) inv.push_back((mod - 1LL * mod / (int)inv.size() * inv[mod % (int)inv.size()]) % mod);
}

template<typename T>
vector<T> precalc_power(T base, int SZ){
	vector<T> res(SZ + 1, 1);
	for(auto i = 1; i <= SZ; ++ i) res[i] = res[i - 1] * base;
	return res;
}

// Store the linear recurrence relation of form Sum{t<=i<t+n}( coef[i] * A[i] ) = A[t+n]
// T must be of modular type
// Requires modular
template<class T>
struct linear_recurrence{
	int n;
	vector<T> init, coef;
	linear_recurrence(const vector<T> &init, const vector<T> &coef): n((int)coef.size()), init(init), coef(coef){
		assert((int)coef.size() == (int)init.size());
	}
	// Berlekamp Massey Algorithm / find the minimal linear recurrence relation
	// O(n * sz + sz log mod)
	linear_recurrence(const vector<T> &s){
		assert(!s.empty());
		int sz = (int)s.size();
		n = 0;
		vector<T> B(sz), C;
		coef.resize(sz);
		coef[0] = B[0] = 1;
		T b = 1;
		for(auto i = 0, m = 0; i < sz; ++ i){
			++ m;
			T d = s[i];
			for(auto j = 1; j <= n; ++ j) d += coef[j] * s[i - j];
			if(!d) continue;
			C = coef;
			T c = d / b;
			for(auto j = m; j < sz; ++ j) coef[j] -= c * B[j - m];
			if(2 * n > i) continue;
			n = i + 1 - n, B = C, b = d, m = 0;
		}
		n = max(n, 1);
		coef.resize(n + 1), coef.erase(coef.begin());
		for(auto &x: coef) x = -x;
		reverse(coef.begin(), coef.end());
		init.resize(n);
		for(auto i = 0; i < n; ++ i) init[i] = s[i];
	}
	// n^2 log i (or n log n log i if FFT is used)
	T operator[](long long i) const{
		assert(0 <= i);
		auto combine = [&](const vector<T> &a, const vector<T> &b){
			vector<T> res(2 * n + 1);
			for(auto i = 0; i <= n; ++ i) for(auto j = 0; j <= n; ++ j) res[i + j] += a[i] * b[j];
			for(auto i = n << 1; i > n; -- i) for(auto j = 0; j < n; ++ j) res[i - 1 - j] += res[i] * coef[n - 1 - j];
			res.resize(n + 1);
			return res;
		};
		vector<T> pol(n + 1), e(pol);
		pol[0] = e[1] = 1;
		for(++ i; i; i >>= 1, e = combine(e, e)) if(i & 1) pol = combine(pol, e);
		T res = 0;
		for(auto i = 0; i < n; ++ i) res += pol[i + 1] * init[i];
		return res;
	}
};

int main(){
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(ios::badbit | ios::failbit);
	int n, m;
	cin >> n >> m;
	vector<string> a(n);
	vector<array<int, 2>> pos;
	vector<vector<int>> invpos(10, vector<int>(10, -1));
	for(auto i = 0; i < n; ++ i){
		cin >> a[i];
		for(auto j = 0; j < (int)a[i].size(); ++ j){
			invpos[i][j] = (int)pos.size();
			pos.push_back({i, j});
		}
	}
	const int sz = (int)pos.size();
	const int mx = 26;
	vector<array<vector<int>, mx>> next_temp(sz);
	for(auto x = 0; x < sz; ++ x){
		auto [i, j] = pos[x];
		if(j + 1 == (int)a[i].size()){
			for(auto c = 0; c < mx; ++ c){
				for(auto k = 0; k < n; ++ k){
					if(a[k][0] - 'a' == c){
						next_temp[x][c].push_back(invpos[k][0]);
					}
				}
			}
		}
		else{
			next_temp[x][a[i][j + 1] - 'a'].push_back(invpos[i][j + 1]);
		}
	}
	vector<vector<pair<int, int>>> next(sz * sz);
	for(auto x = 0; x < sz; ++ x){
		for(auto y = 0; y < sz; ++ y){
			vector<int> cnt(sz * sz);
			for(auto c = 0; c < mx; ++ c){
				for(auto z: next_temp[x][c]){
					for(auto w: next_temp[y][c]){
						++ cnt[sz * z + w];
					}
				}
			}
			for(auto t = 0; t < sz * sz; ++ t){
				if(cnt[t]){
					next[sz * x + y].push_back({t, cnt[t]});
				}
			}
		}
	}
	vector dp({vector<Zp>(sz * sz)});
	dp[0][(sz + 1) * invpos[0][(int)a[0].size() - 1]] = 1;
	for(auto t = 0; t < 2 * sz * sz; ++ t){
		const vector<Zp> &dp_cur = dp[t];
		vector<Zp> dp_next(sz * sz);
		for(auto x = 0; x < sz * sz; ++ x){
			for(auto [y, val]: next[x]){
				dp_next[y] += dp_cur[x] * val;
			}
		}
		dp.push_back(dp_next);
	}
	Zp res = 0;
	for(auto i = 0; i < n; ++ i){
		for(auto j = 0; j < n; ++ j){
			int u = sz * invpos[i][(int)a[i].size() - 1] + invpos[j][(int)a[j].size() - 1];
			vector<Zp> cur((int)dp.size());
			for(auto t = 0; t < (int)dp.size(); ++ t){
				cur[t] = dp[t][u];
			}
			linear_recurrence<Zp> f(cur);
			res += f[m];
		}
	}
	cout << res << "\n";
	return 0;
}

/*
40 ^ 4

2560000
*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//                                   Coded by Aeren                                   //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////////

#include <bits/stdc++.h>

using namespace std;

using db = double;
using s64 = long long;
using ld = long double;
using u32 = unsigned int;
using u64 = unsigned long long;

using pii = pair<int, int>;
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)

#define For(i, a, b) for (decay<decltype(b)>::type i = (a), _##i = (b); i <= _##i; ++i)
#define Ford(i, a, b) for (decay<decltype(a)>::type i = (a), _##i = (b); i >= _##i; --i)
#define FOR(i, a, b) for (decay<decltype(b)>::type i = (a), _##i = (b); i < _##i; ++i)
#define FORD(i, a, b) for (decay<decltype(a)>::type i = (a) - 1, _##i = (b); i >= _##i; --i)

#ifdef LOCAL
#define Debug(x...) do { cout << "\033[32;1m" << #x << " -> "; Err(x); } while (0)
void Err() { cout << "\033[39;0m" << endl; }
template<template<typename...> class T, typename t, typename... A>
void Err(T<t> a, A... x) { for (auto v: a) cout << v << ' '; err(x...); }
template<typename T, typename... A>
void Err(T a, A... x) { cout << a << ' '; err(x...); }
#else
#define Debug(...)
#endif

#define all(x) x.begin(), x.end()

const double PI = acos(-1);
const double eps = 1e-7;

const int P = 998244353;
int Add(int x, int y) {return (x += y) >= P ? x - P : x;}
int Dec(int x, int y) {return (x -= y) < 0 ? x + P : x;}
int Mult(int &x, int y) {return x = (s64) x * y % P;}
int add(int &x, int y) {return (x += y) >= P ? x -= P : x;}
int dec(int &x, int y) {return (x -= y) < 0 ? x += P : x;}
int mult(int x, int y) {return (s64) x * y % P;}
int fpw(int x, int k = P - 2) {
	int res = 1;
	for (; k; k >>= 1, x = mult(x, x))
		if (k & 1) res = mult(res, x);
	return res;
}

namespace Solver {
    const char endl = '\n';
	const int MT = 41, K = 26;
	struct Matrix {
		int a[MT * MT][MT * MT], N;
		Matrix() = default;
		Matrix (int n) {N = n; FOR (i, 0, N) FOR (j, 0, N) a[i][j] = 0;}
		Matrix operator * (const Matrix &b) const {
			Matrix res(N);
			FOR (i, 0, N) FOR (k, 0, N) if (a[i][k]) FOR (j, 0, N)
				add(res.a[i][j], mult(a[i][k], b.a[k][j]));
			return res;
		}
	}A, S;
	map<pii, int> f;
	int n, m, tcnt, vcnt, ch[MT][K];
	bool isEnd[MT], vis[MT * MT];
	Matrix calc(Matrix x, int k) {
		Matrix res = Matrix(vcnt);
		FOR (i, 0, vcnt) res.a[i][i] = 1;
		for (; k; k >>= 1, x = x * x)
			if (k & 1) res = res * x;
		return res;
	}
	void main() {
		cin >> n >> m;
		For (i, 1, n) {
			string s;
			cin >> s;
			int u = 0;
			for (auto c : s) {
				if (!ch[u][c - 'a']) ch[u][c - 'a'] = ++tcnt;
				u = ch[u][c - 'a'];
			}
			isEnd[u] = 1;
		}
		auto getIndex = [](const int &x, const int &y) {
			pii u = mp(x, y);
			if (f.find(u) != f.end()) return f[u];
			return f[u] = vcnt++;
		};
		queue<pii> q;
		q.emplace(0, 0);
		vis[getIndex(0, 0)] = 1;
		for (; !q.empty(); q.pop()) {
			auto [x, y] = q.front();
			int u = getIndex(x, y);
			FOR (i, 0, K)
				if (ch[x][i] && ch[y][i]) {
					int nx = ch[x][i], ny = ch[y][i];
					bool flagx = false, flagy = false;
					FOR (j, 0, K)
						flagx |= ch[nx][j],
						flagy |= ch[ny][j];
					if (flagx && flagy) {
						int v = getIndex(nx, ny);
						if (!vis[v]) q.emplace(nx, ny);
						vis[v] = 1;
						++A.a[u][v];
					}
					if (flagx && isEnd[ny]) {
						int v = getIndex(nx, 0);
						if (!vis[v]) q.emplace(nx, 0);
						vis[v] = 1;
						++A.a[u][v];
					}
					if (isEnd[nx] && flagy) {
						int v = getIndex(0, ny);
						if (!vis[v]) q.emplace(0, ny);
						vis[v] = 1;
						++A.a[u][v];
					}
					if (isEnd[nx] && isEnd[ny]) {
						int v = getIndex(0, 0);
						if (!vis[v]) q.emplace(0, 0);
						vis[v] = 1;
						++A.a[u][v];
					}
				}
		}
		S.N = A.N = vcnt;
		S.a[0][0] = 1;
		cout << (S * calc(A, m)).a[0][0] << endl;
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int T = 1;
	//cin >> T;
	For(_t, 1, T) {
		// cout << "Case #" << _t << ": ";
		// cout << endl;
		Solver::main();
	}
	return 0;
}

//#define _GLIBCXX_DEBUG

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
  auto tmp = v;
  for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
  rearrange(ord, head);
  rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]<v[j];});
  return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]>v[j];});
  return ord;
}
ll FLOOR(ll n,ll div){return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){return n>=0?(n+div-1)/div:n/div;}
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
template< typename T = int >
struct edge {
  int to;
  T cost;
  int id;
  edge() = default;
  edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
  operator int() const { return to; }
};

template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
  Graph<T> ret(n);
  for(int es = 0; es < m; es++){
    int u,v,w=1;
    cin>>u>>v;u-=indexed,v-=indexed;
    if(weighted)cin>>w;
    ret[u].emplace_back(v,w,es);
    if(!directed)ret[v].emplace_back(u,w,es);
  }
  return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
  Graph<T>ret(n);
  for(int i=1;i<n;i++){
    int p;cin>>p;
    p-=indexed;
    ret[p].emplace_back(i);
    if(!directed)ret[i].emplace_back(p);
  }
  return ret;
}
template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  friend ModInt operator+(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) += rhs;
  }
  friend ModInt operator-(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) -= rhs;
  }
  friend ModInt operator*(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) *= rhs;
  }
  friend ModInt operator/(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) /= rhs;
  }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;

  Combination(ll sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(ll i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(ll i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(ll i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }

  inline T fact(ll k) const { return _fact[k]; }

  inline T rfact(ll k) const { return _rfact[k]; }

  inline T inv(ll k) const { return _inv[k]; }

  T P(ll n, ll r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }

  T C(ll p, ll q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }

  T RC(ll p, ll q) const {
    if(q < 0 || p < q) return 0;
    return rfact(p) * fact(q) * fact(p - q);
  }

  T H(ll n, ll r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
using modint = ModInt< MOD9 >;modint pow(ll n, ll x){return modint(n).pow(x);}modint pow(modint n, ll x){return n.pow(x);}
//using modint=ld;
using Comb=Combination<modint>;

template< class T >
struct Matrix {
  vector< vector< T > > A;

  Matrix() {}

  Matrix(size_t n, size_t m) : A(n, vector< T >(m, 0)) {}

  Matrix(size_t n) : A(n, vector< T >(n, 0)) {};

  Matrix(vector<vector<T>>v):A(v){};

  size_t height() const {
    return (A.size());
  }

  size_t width() const {
    return (A[0].size());
  }

  inline const vector< T > &operator[](int k) const {
    return (A.at(k));
  }

  inline vector< T > &operator[](int k) {
    return (A.at(k));
  }

  static Matrix I(size_t n) {
    Matrix mat(n);
    for(int i = 0; i < n; i++) mat[i][i] = 1;
    return (mat);
  }

  Matrix &operator+=(const Matrix &B) {
    size_t n = height(), m = width();
    assert(n == B.height() && m == B.width());
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        (*this)[i][j] += B[i][j];
    return (*this);
  }

  Matrix &operator-=(const Matrix &B) {
    size_t n = height(), m = width();
    assert(n == B.height() && m == B.width());
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        (*this)[i][j] -= B[i][j];
    return (*this);
  }

  Matrix &operator*=(const Matrix &B) {
    size_t n = height(), m = B.width(), p = width();
    assert(p == B.height());
    vector< vector< T > > C(n, vector< T >(m, 0));
    for(int i = 0; i < n; i++)
      for(int j = 0; j < m; j++)
        for(int k = 0; k < p; k++)
          C[i][j] = (C[i][j] + (*this)[i][k] * B[k][j]);
    A.swap(C);
    return (*this);
  }

  Matrix &operator^=(long long k) {
    Matrix B = Matrix::I(height());
    while(k > 0) {
      if(k & 1) B *= *this;
      *this *= *this;
      k >>= 1LL;
    }
    A.swap(B.A);
    return (*this);
  }

  Matrix operator+(const Matrix &B) const {
    return (Matrix(*this) += B);
  }

  Matrix operator-(const Matrix &B) const {
    return (Matrix(*this) -= B);
  }

  Matrix operator*(const Matrix &B) const {
    return (Matrix(*this) *= B);
  }

  Matrix operator^(const long long k) const {
    return (Matrix(*this) ^= k);
  }

  friend ostream &operator<<(ostream &os, Matrix p) {
    size_t n = p.height(), m = p.width();
    for(int i = 0; i < n; i++) {
      os << "[";
      for(int j = 0; j < m; j++) {
        os << p[i][j] << (j + 1 == m ? "]\n" : ",");
      }
    }
    return (os);
  }

  T determinant() {
    Matrix B(*this);
    assert(width() == height());
    T ret = 1;
    for(int i = 0; i < width(); i++) {
      int idx = -1;
      for(int j = i; j < width(); j++) {
        if(B[j][i] != 0) idx = j;
      }
      if(idx == -1) return (0);
      if(i != idx) {
        ret *= -1;
        swap(B[i], B[idx]);
      }
      ret *= B[i][i];
      T vv = B[i][i];
      for(int j = 0; j < width(); j++) {
        B[i][j] /= vv;
      }
      for(int j = i + 1; j < width(); j++) {
        T a = B[j][i];
        for(int k = 0; k < width(); k++) {
          B[j][k] -= B[i][k] * a;
        }
      }
    }
    return (ret);
  }
};
template<typename T>
map<T,ll> compress(vector<T> &v){
  sort(ALL(v));
  v.erase(unique(ALL(v)),v.end());
  map<T, ll> ret;
  for(ll i=0;i<(ll)v.size();i++)
    ret[v[i]]=i;
  return ret;
}
int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
  ll n,m;cin>>n>>m;
  vector<string>s(n);
  rep(i,0,n)cin>>s[i];
  vector<string>vs;
  vs.PB("");
  rep(i,0,n){
    rep(j,0,s[i].size())vs.PB(s[i].substr(j));
  }
  auto mp=compress(vs);
  ll sz=mp.size();
  Matrix<modint>mat(sz*5,sz*5);
  rep(i,sz,5*sz){
    mat[i][i-sz]=1;
  }
  rep(i,0,sz){
    rep(j,0,n){
      string p=vs[i],q=s[j];
      ll np=vs[i].size();
      ll nq=s[j].size();
      if(np>nq){
        swap(np,nq);
        swap(p,q);
      }
      bool sw=true;
      rep(o,0,np)if(p[o]!=q[o])sw=false;
      if(sw){
        mat[i][mp[q.substr(np)]+sz*(s[j].size()-1)]+=1;
        //cout<<p spa q spa q.substr(np)<<endl;
      }
    }
  }
  //cout<<mat<<endl;
  mat^=m*2;
  //cout<<mat<<endl;
  //debug(vs,vs.size());
  cout<<mat[mp[""]][mp[""]]<<endl;
  return 0;
}

#include <bits/stdc++.h>

using namespace std;
typedef long long Int;
const int N = 45;
const int p = 998244353;

int cnt;
int fa[N];
int val[N];
int isEnd[N];
int ch[N][26];

struct Matrix {
    int n, m;
    vector<vector<Int>> vec;

    Matrix(int n, int m) : n{n}, m{m}, vec(n, vector<Int>(m)) {}
};

Matrix operator*(Matrix &x, Matrix &y) {
    Matrix z(x.n, y.m);
    for (int i = 0; i < x.n; ++i)
        for (int j = 0; j < x.m; ++j)
            for (int k = 0; k < y.m; ++k)
                (z.vec[i][k] += x.vec[i][j] * y.vec[j][k]) %= p;
    return z;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        char s[6];
        cin >> s;
        int x = 0;
        for (int j = 0; s[j]; ++j) {
            int c = s[j] - 'a';
            if (!ch[x][c]) {
                ch[x][c] = ++cnt;
                fa[cnt] = x;
                val[cnt] = c;
            }
            x = ch[x][c];
        }
        isEnd[x] = 1;
    }
    vector<pair<int, int>> vec;
    for (int i = 1; i <= cnt; i++)
        for (int j = 1; j <= cnt; j++) {
            for (int x = i, y = j; x; x = fa[x], y = fa[y])
                if (val[x] != val[y] || !y) goto loop;
            vec.emplace_back(i, j);
            loop:;
        }
    n = (int) vec.size();
    Matrix X(n, n);
    for (int i = 0; i < n; ++i) {
        int x = vec[i].first;
        int y = vec[i].second;
        for (int c = 0; c < 26; ++c) {
            if (ch[x][c] && ch[y][c])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[x][c], ch[y][c])) - vec.begin()] = 1;
            if (ch[0][c] && ch[y][c] && isEnd[x])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[0][c], ch[y][c])) - vec.begin()] = 1;
            if (ch[x][c] && ch[0][c] && isEnd[y])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[0][c], ch[x][c])) - vec.begin()] = 1;
            if (ch[0][c] && isEnd[x] && isEnd[y])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[0][c], ch[0][c])) - vec.begin()] = x == y ? 1 : 2;
        }
    }
    Matrix Y(n, n);
    for (int i = 0; i < n; ++i) Y.vec[i][i] = 1;
    for (; m; m >>= 1) {
        if (m & 1)
            Y = X * Y;
        X = X * X;
    }
    Int ans = 0;
    for (int i = 0; i < n; ++i) {
        int x = vec[i].first;
        int y = vec[i].second;
        if (isEnd[x] && isEnd[y])
            ans += Y.vec[n - 1][i] * (x == y ? 1 : 2);
    }
    cout << ans % p << endl;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;
typedef long long Int;
const int N = 50;
const int p = 998244353;

int cnt;
int fa[N];
int val[N];
int is_end[N];
int ch[N][26];

struct Matrix {
    int n, m;
    vector<vector<Int>> vec;

    Matrix(int n, int m) : n{n}, m{m}, vec(n, vector<Int>(m)) {}
};

Matrix operator*(Matrix &x, Matrix &y) {
    Matrix z(x.n, y.m);
    for (int i = 0; i < x.n; ++i)
        for (int j = 0; j < x.m; ++j)
            for (int k = 0; k < y.m; ++k)
                z.vec[i][k] += x.vec[i][j] * y.vec[j][k] % p;
    for (int i = 0; i < z.n; ++i)
        for (int j = 0; j < z.m; ++j)
            z.vec[i][j] %= p;
    return z;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        char s[6];
        cin >> s;
        int x = 0;
        for (int j = 0; s[j]; ++j) {
            int c = s[j] - 'a';
            if (!ch[x][c]) {
                ch[x][c] = ++cnt;
                fa[cnt] = x;
                val[cnt] = c;
            }
            x = ch[x][c];
        }
        is_end[x] = 1;
    }
    vector<pair<int, int>> vec;
    for (int i = 1; i <= cnt; i++)
        for (int j = 1; j <= cnt; j++) {
            for (int x = i, y = j; x; x = fa[x], y = fa[y])
                if (val[x] != val[y] || !y) goto loop;
            vec.emplace_back(i, j);
            loop:;
        }
    n = (int) vec.size();
    Matrix X(n, n);
    for (int i = 0; i < n; ++i) {
        int x = vec[i].first;
        int y = vec[i].second;
        for (int c = 0; c < 26; ++c) {
            if (ch[x][c] && ch[y][c])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[x][c], ch[y][c])) - vec.begin()] = 1;
            if (ch[0][c] && ch[y][c] && is_end[x])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[0][c], ch[y][c])) - vec.begin()] = 1;
            if (ch[x][c] && ch[0][c] && is_end[y])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[0][c], ch[x][c])) - vec.begin()] = 1;
            if (ch[0][c] && is_end[x] && is_end[y])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[0][c], ch[0][c])) - vec.begin()] = x == y ? 1 : 2;
        }
    }
    Matrix A(n, n);
    for (int i = 0; i < n; ++i) A.vec[i][i] = 1;
    for (; m; m >>= 1) {
        if (m & 1)
            A = X * A;
        X = X * X;
    }
    Int ans = 0;
    for (int i = 0; i < n; ++i) {
        int x = vec[i].first;
        int y = vec[i].second;
        if (is_end[x] && is_end[y])
            ans += A.vec[n - 1][i] * (x == y ? 1 : 2);
    }
    cout << ans % p << endl;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef vector<vector<ll>> mat;

const int K=26;

struct Vertex
{
    char c;
    int p;
    array<int,K> trie;
    array<int,K> go;
    int link;
    bool leaf;
    Vertex(char nc='$',int np=-1)
    {
        c=nc;
        p=np;
        trie.fill(-1);
        go.fill(-1);
        link=-1;
        leaf=0;
    }
};

vector<Vertex> ac(1);

void add(string s)
{
    int a=0;
    for(char t:s)
    {
        int c=(t-'a');
        if(ac[a].trie[c]==-1)
        {
            ac.push_back(Vertex(t,a));
            ac[a].trie[c]=(int)ac.size()-1;
        }
        a=ac[a].trie[c];
    }
    ac[a].leaf=1;
}

int go(int a,char t);

int get_link(int a)
{
    if(ac[a].link==-1)
    {
        if(a==0||ac[a].p==0) ac[a].link=0;
        else ac[a].link=go(get_link(ac[a].p),ac[a].c);
    }
    return ac[a].link;
}

int go(int a,char t)
{
    int c=(t-'a');
    if(ac[a].go[c]==-1)
    {
        if(ac[a].trie[c]!=-1) ac[a].go[c]=ac[a].trie[c];
        else ac[a].go[c]=(a==0?0:go(get_link(a),t));
    }
    return ac[a].go[c];
}

int D;
const ll mod=998244353;

mat id()
{
    mat a(D,vector<ll>(D,0));
    for(int i=0;i<D;i++) a[i][i]=1;
    return a;
}

mat operator*(const mat &a,const mat &b)
{
    mat c(D,vector<ll>(D,0));
    for(int i=0;i<D;i++) for(int j=0;j<D;j++) for(int k=0;k<D;k++) c[i][k]=(c[i][k]+a[i][j]*b[j][k])%mod;
    return c;
}

mat fpow(mat b,int e)
{
    mat res=id();
    while(e)
    {
        if(e&1) res=res*b;
        b=b*b;
        e/=2;
    }
    return res;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n,m;
    cin >> n >> m;
    for(int i=0;i<n;i++)
    {
        string s;
        cin >> s;
        add(s);
    }
    int sz=(int)ac.size()-1;
    vector<array<int,2>> opt;
    map<array<int,2>,int> rev;
    for(int i=0;i<=sz;i++)
    {
        opt.push_back({i,i});
        int j=i;
        while(j!=0)
        {
            j=get_link(j);
            opt.push_back({min(i,j),max(i,j)});
        }
    }
    D=opt.size();
    for(int i=0;i<D;i++) rev[opt[i]]=i;
    mat a(D,vector<ll>(D,0));
    for(int now=0;now<D;now++)
    {
        auto [i,j]=opt[now];
        for(int c=0;c<26;c++)
        {
            if(ac[i].trie[c]==-1||ac[j].trie[c]==-1) continue;
            int ti=ac[i].trie[c];
            int tj=ac[j].trie[c];
            for(int x=0;x<=ac[ti].leaf;x++)
            {
                for(int y=0;y<=ac[tj].leaf;y++)
                {
                    int ni=(x==0?ti:0);
                    int nj=(y==0?tj:0);
                    int nxt=rev[{min(ni,nj),max(ni,nj)}];
                    a[nxt][now]++;
                }
            }
        }
    }
    cout << fpow(a,m)[0][0] << "\n";
    return 0;
}

#include <iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#include<ctime>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<bitset>
#define sqr(x) ((x)*(x))
#define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
#define fd1(i,n) for ((i)=(n);(i)>=1;(i)--)
#define fz0g(i,n) for ((i)=0;(i)<=(n);(i)++)
#define fd0g(i,n) for ((i)=(n);(i)>=0;(i)--)
#define fz0k(i,n) for ((i)=0;(i)<(n);(i)++)
#define fd0k(i,n) for ((i)=(long long)((n)-1);(i)>=0;(i)--)
#define fz(i,x,y) for ((i)=(x);(i)<=(y);(i)++)
#define fd(i,y,x) for ((i)=(y);(i)>=(x);(i)--)
#define fzin fz1(i,n)
#define fzim fz1(i,m)
#define fzjn fz1(j,n)
#define fzjm fz1(j,m)
#define ff(c,itr) for (__typeof((c).begin()) itr=(c).begin();itr!=(c).end();++itr)
#define rdst(st,len){static char ss[len];scanf(" %s",ss);(st)=ss;}
#define incm(x,y) {x=((x)+(y))%mod;}
#define spln(i,n) (i==n?'\n':' ')
#define fac_init(n){fac[0]=fac[1]=inv[1]=fi[0]=fi[1]=1;fz(i,2,n){fac[i]=1ll*fac[i-1]*i%mod;inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;fi[i]=1ll*fi[i-1]*inv[i]%mod;}}
#define fi first
#define se second
#define mk make_pair
using namespace std;
inline void read(int &x)
{
	char c;int f=1;
	while(!isdigit(c=getchar()))if(c=='-')f=-1;
	x=(c&15);while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);
	x*=f;
}
const int mod=998244353;
const long long mod2=1ll*mod*mod;
int n,m,i,j,k,cnt=1,ch[45][26],ed[45];
int a[1005][1005],b[1005][1005];
long long c[1005][1005];
string st;
int id[45][45],cid;
void dfs(int x,int y)
{
	if(id[x][y]) return;
	id[x][y]=++cid;
	if(ed[x]) dfs(1,y);
	if(ed[y]) dfs(x,1);
	int i;
	fz0k(i,26)if(ch[x][i]&&ch[y][i])dfs(ch[x][i],ch[y][i]);
}
int main()
{
	cin>>n>>m;
	while(n--){
		cin>>st;
		int x=1;
		fz0k(i,st.size()){
			if(!ch[x][st[i]-'a']){
				ch[x][st[i]-'a']=++cnt;
			}
			x=ch[x][st[i]-'a'];
		}
		ed[x]++;
	}
	dfs(1,1);
	int x,y;
	fz1(x,cnt)fz1(y,cnt)if(id[x][y]){
		fz0k(i,26)if(ch[x][i]&&ch[y][i]){
			a[id[x][y]][id[ch[x][i]][ch[y][i]]]+=1;
			a[id[x][y]][id[ch[x][i]][1]]+=ed[ch[y][i]];
			a[id[x][y]][id[1][ch[y][i]]]+=ed[ch[x][i]];
			a[id[x][y]][id[1][1]]+=ed[ch[x][i]]*ed[ch[y][i]];
		}
	}
//	fz1(x,cnt)fz1(y,cnt)fz1(i,cnt)fz1(j,cnt)if(a[id[x][y]][id[i][j]]){
//		cerr<<x<<' '<<y<<' '<<i<<' '<<j<<' '<<a[id[x][y]][id[i][j]]<<endl;
//	}
	fz1(i,cid) b[i][i]=1;
	while(m){
		if(m&1){
			fz1(i,cid)fz1(j,cid){
				c[i][j]=0;
				fz1(k,cid){
					c[i][j]=(c[i][j]+1ll*a[i][k]*b[k][j]);
					if(c[i][j]>=mod2)c[i][j]-=mod2;
				}
			}
			fz1(i,cid)fz1(j,cid){
				b[i][j]=c[i][j]%mod;
			}
		}
		m/=2;
		fz1(i,cid)fz1(j,cid){
			c[i][j]=0;
			fz1(k,cid){
				c[i][j]=(c[i][j]+1ll*a[i][k]*a[k][j]);
				if(c[i][j]>=mod2)c[i][j]-=mod2;
			}
		}
		fz1(i,cid)fz1(j,cid){
			a[i][j]=c[i][j]%mod;
		}
	}
	cout<<b[id[1][1]][id[1][1]]<<endl;
	return 0;
}

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define ll long long
#define pb push_back
#define f first
#define s second
#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL)
#define D(x) cerr << #x << " is " << (x) << "\n";
#define ld long double
#define li __int128

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>; ///find_by_order(),order_of_key()
template<int D, typename T>struct vec : public vector<vec<D - 1, T>> {template<typename... Args>vec(int n = 0, Args... args) : vector<vec<D - 1, T>>(n, vec<D - 1, T>(args...)) {}};
template<typename T>struct vec<1, T> : public vector<T> {vec(int n = 0, T val = T()) : vector<T>(n, val) {}};
template<class T1,class T2> ostream& operator<<(ostream& os, const pair<T1,T2>& a) { os << '{' << a.f << ", " << a.s << '}'; return os; }
template<class T> ostream& operator<<(ostream& os, const vector<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const deque<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T,greater<T> >& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T,greater<T> >& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> ostream& operator<<(ostream& os, const map<T1,T2>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> istream& operator>>(istream& is,pair<T1,T2>& a) {is>>a.f>>a.s;return is;}
template<class T> istream& operator>>(istream& is,vector<T>& a) {for(auto &p:a)is>>p;return is;}
int ri(){int x;scanf("%i",&x);return x;}
void rd(int&x){scanf("%i",&x);}
void rd(long long&x){scanf("%lld",&x);}
void rd(double&x){scanf("%lf",&x);}
void rd(long double&x){scanf("%Lf",&x);}
void rd(string&x){cin>>x;}
void rd(char*x){scanf("%s",x);}
template<typename T1,typename T2>void rd(pair<T1,T2>&x){rd(x.first);rd(x.second);}
template<typename T>void rd(vector<T>&x){for(T&p:x)rd(p);}
template<typename C,typename...T>void rd(C&a,T&...args){rd(a);rd(args...);}
//istream& operator>>(istream& is,__int128& a){string s;is>>s;a=0;int i=0;bool neg=false;if(s[0]=='-')neg=true,i++;for(;i<s.size();i++)a=a*10+s[i]-'0';if(neg)a*=-1;return is;}
//ostream& operator<<(ostream& os,__int128 a){bool neg=false;if(a<0)neg=true,a*=-1;ll high=(a/(__int128)1e18);ll low=(a-(__int128)1e18*high);string res;if(neg)res+='-';if(high>0){res+=to_string(high);string temp=to_string(low);res+=string(18-temp.size(),'0');res+=temp;}else res+=to_string(low);os<<res;return os;}

const int mod=998244353;
int add(int a,int b){
    a+=b;
    if(a>=mod)
        a-=mod;
    return a;
}
int sub(int a,int b){
    a-=b;
    if(a<0)
        a+=mod;
    return a;
}
int mul(int a,int b){
    return (long long)a*b%mod;
}
int pwrmod(int x,int k){
    int ans=1;
    for(;k;k>>=1,x=mul(x,x))
        if(k&1)
            ans=mul(ans,x);
    return ans;
}

const int N=41,L=26;
vector<int> nxt[N][L];
bool kr[N];
bool pref(string a,string b){
	if(a.size()<b.size())
		return pref(b,a);
	return a.substr(a.size()-b.size(),b.size())==b;
}
vector<vector<int>> mul(vector<vector<int>> &a,vector<vector<int>> &b){
	int n=a.size(),m=b[0].size(),l=a[0].size();
	assert(a[0].size()==b.size());
	vector<vector<int>> sol(n,vector<int>(m,0));
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			for(int k=0;k<l;k++)
				sol[i][j]=add(sol[i][j],mul(a[i][k],b[k][j]));
	return sol;
}
int main()
{
	int n=ri(),m=ri();
	vector<string> s(n);
	rd(s);
	map<string,int> done;
	int ind=0;
	vector<string> pre;

	//done[""]=ind++;pre.pb("");

	for(int i=0;i<n;i++){
		string tr;
		for(int j=0;j<s[i].size();j++){
			tr+=s[i][j];
			if(done.find(tr)==done.end()){
				done[tr]=ind++;
				pre.pb(tr);
			}
			if(j==s[i].size()-1){
				kr[done[tr]]=1;
			}
		}
	}
	for(auto p:done){
		string tr=p.f;
		int i=p.s;
		for(int j=0;j<26;j++){
			char c='a'+j;
			string novi=tr+c,o;
			o+=c;
			if(done.find(novi)!=done.end())
				nxt[i][j].pb(done[novi]);
			if(kr[i]&&done.find(o)!=done.end())
				nxt[i][j].pb(done[o]);
		}
	}
	vector<pair<int,int>> pr;
	map<pair<int,int>,int> koji;
	for(int i=0;i<ind;i++)
		for(int j=0;j<ind;j++)
			if(pref(pre[i],pre[j])){
				pr.pb({i,j});
				koji[{i,j}]=pr.size()-1;
			}
	int L=pr.size();
	vector<vector<int>> mulMat(L,vector<int>(L,0));
	for(int k=0;k<L;k++){
		int i=pr[k].f,j=pr[k].s;
		for(int l=0;l<26;l++){
			for(auto p:nxt[i][l])
				for(auto d:nxt[j][l]){
					if(koji.find({p,d})!=koji.end()){
						int sl=koji[{p,d}];
						mulMat[k][sl]=add(mulMat[k][sl],1);
					}
				}
		}
	}
	vector<vector<int>> begMat(1,vector<int>(L,0));
	m--;
	for(int k=0;k<L;k++){
		int i=pr[k].f,j=pr[k].s;
		if(i!=j)
			continue;
		if(pre[i].size()==1)
			begMat[0][k]++;
	}
	for(;m;m>>=1,mulMat=mul(mulMat,mulMat))
		if(m&1)
			begMat=mul(begMat,mulMat);
	int sol=0;
	for(int k=0;k<L;k++){
		int i=pr[k].f,j=pr[k].s;
		if(kr[i]&&kr[j])
			sol=add(sol,begMat[0][k]);
	}
	printf("%i\n",sol);
	return 0;
}

#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
//?
#define x first
#define y second

using namespace std;

using i64 = long long;
using PII = pair<int, int>;

const int N = 210;
const int mod = 998244353;

bool ed[N];
int tr[N][26], idx;
PII q[N * N];
map<PII, int> mp;
int ids;
int tt = -1, hh;
int n, m;

void add(i64& x, i64 v) {
    x += v;
    if (x >= mod) x %= mod;
}

struct Matrix {
    i64 v[N][N];
    Matrix(int t = 0) {
        memset(v, 0, sizeof v);
        if (t) {
            for (int i = 0; i < ids; i++)
                v[i][i] = 1;
        }
    }
    Matrix operator* (const Matrix& b) const {
        Matrix res;
        for (int i = 0; i < ids; i++)
            for (int j = 0; j < ids; j++)
                for (int k = 0; k < ids; k++)
                    add(res.v[i][j], v[i][k] * b.v[k][j]);
        return res;
    }
    Matrix operator^ (int b) const {
        Matrix res(1), a = *this;
        while (b) {
            if (b & 1) res = res * a;
            a = a * a;
            b >>= 1;
        }
        return res;
    }
}trans;

int get(int x, int y) {
    if (x > y) swap(x, y);
    if (!mp.count({x, y})) {
        mp[{x, y}] = ids++;
        q[++tt] = {x, y};
    }
    return mp[{x, y}];
}

void insert() {
    string s;
    cin >> s;
    int p = 0;
    for (int i = 0; s[i]; i++) {
        int c = s[i] - 'a';
        if (!tr[p][c]) tr[p][c] = ++idx;
        p = tr[p][c];
    }
    ed[p] = true;
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) insert();
    get(0, 0);
    while (hh <= tt) {
        auto& [x, y] = q[hh++];
        int from = get(x, y);
        for (int i = 0; i < 26; i++) {
            int tx = tr[x][i], ty = tr[y][i];
            if (!tx || !ty) continue;
            trans.v[from][get(tx, ty)]++;
            if (ed[tx]) trans.v[from][get(0, ty)]++;
            if (ed[ty]) trans.v[from][get(tx, 0)]++;
            if (ed[tx] && ed[ty]) trans.v[from][0]++;
        }
    }
    Matrix mat;
    mat.v[0][0] = 1;
    mat = mat * (trans ^ m);
    cout << mat.v[0][0];
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353,N=165;
int ch[N][N],ed[N],id[N][N],tot;
struct mat{ll a[N][N];}M;
mat operator*(const mat &a,const mat &b){
    mat r;memset(r.a,0,sizeof r.a);
    for(int i=1;i<=tot;i++)for(int k=1;k<=tot;k++)for(int j=1;j<=tot;j++)(r.a[i][j]+=a.a[i][k]*b.a[k][j])%=mod;
    return r;
}
int dfs(int x,int y){
    auto&u=id[x][y];if(u)return u;
    u=id[y][x]=++tot;
    for(int i=0;i<26;i++){
        int nx=ch[x][i],ny=ch[y][i];
        if(nx&&ny){
            M.a[u][dfs(nx,ny)]++;
            if(ed[nx])M.a[u][dfs(1,ny)]++;
            if(ed[ny])M.a[u][dfs(1,nx)]++;
            if(ed[ny]&&ed[nx])M.a[u][dfs(1,1)]++;
        }
    }
    return u;
}
int main(){
    int n,m,p,sz=1;cin>>n>>m,--m;string s;
    while(n--){
        cin>>s,p=1;
        for(auto c:s){
            auto&nx=ch[p][c-'a'];
            if(!nx)nx=++sz;p=nx;
        }ed[p]=1;
    }
    dfs(1,1);mat r=M;
    for(;m;m>>=1,M=M*M)if(m&1)r=r*M;
    cout<<r.a[1][1];
}

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 22;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

typedef vector<vector<modint>> mat;
typedef vector<modint> vec;
mat mtmul(mat& A, mat& B) {
	mat C(A.size(), vec(B[0].size()));
	rep(i, (int)A.size()) {
		rep(k, (int)B.size()) {
			rep(j, (int)B[0].size()) {
				C[i][j] += A[i][k] * B[k][j];
			}
		}
	}
	return C;
}
mat mtpow(mat A, ll n) {
	mat B(A.size(), vec(A.size()));
	rep(i, (int)A.size()) {
		B[i][i] = 1;
	}
	while (n > 0) {
		if (n & (ll)1)B = mtmul(B, A);
		A = mtmul(A, A);
		n >>= 1;
	}
	return B;
}
void solve() {
	int n, m; cin >> n >> m;
	vector<string> s(n);
	rep(i, n)cin >> s[i];
	vector<int> ad(n);
	int c = 0;
	rep(i, n) {
		ad[i] = c; c += s[i].size();
	}
	int t = c + 1;
	mat A(5*t,vector<modint>(5*t));
	for (int i = t; i < 5 * t; i++) {
		A[i - t][i] = 1;
	}
	rep(i, n)rep(j, s[i].size()) {
		rep(k, n) {
			string sl = s[i].substr(j, s[i].size() - j);
			string sr = s[k];
			if (sl.size() < sr.size()) {
				string sx = sr.substr(0, sl.size());
				if (sl == sx) {
					int fr = ad[i] + j;
					int sc = ad[k] + sl.size()+(sl.size()-1)*t;
					A[sc][fr] += 1;
				}
			}
			else if (sl.size() > sr.size()) {
				string sx = sl.substr(0, sr.size());
				if (sr == sx) {
					int fr = ad[i] + j;
					int sc = ad[i] + j + sr.size() + (sr.size() - 1) * t;
					A[sc][fr] += 1;
				}
			}
			else {
				if (sl == sr) {
					int fr = ad[i] + j;
					int sc = c+(sl.size() - 1) * t;
					//cout << 5 * t << " " <<sc <<" "<<fr<< "\n";
					A[sc][fr] += 1;
				}
			}
		}
	}
	rep(i, n)rep(j, n) {
		string sl = s[i];
		string sr = s[j];
		if (sl.size() < sr.size()) {
			string sx = sr.substr(0, sl.size());
			if (sl == sx) {
				int fr = c;
				int sc = ad[j] + sl.size() + (sl.size() - 1) * t;
				A[sc][fr] += 1;
			}
		}
		else if (sl.size() > sr.size()) {
			string sx = sl.substr(0, sr.size());
			if (sr == sx) {
				int fr = c;
				int sc = ad[i] + sr.size() + (sr.size() - 1) * t;
				A[sc][fr] += 1;
			}
		}
		else {
			if (sl == sr) {
				int fr = c;
				int sc = c + (sl.size() - 1) * t;
				A[sc][fr] += 1;
			}
		}
	}
	A = mtpow(A, m);
	cout << A[c][c] << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}

#include <cstdio>
#include <cstring>

//#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define print(x,y) write(x),putchar(y)

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}

const int mod=998244353,bas=42;

inline void inc(int &x,int y) {
	x=(x+y>=mod)?x+y-mod:x+y;
}

struct Mat {
	int n,m,a[201][201];
	Mat() {n=m=0,memset(a,0,sizeof a);}

	Mat operator * (const Mat &t) const {
		Mat r; r.n=n,r.m=t.m;
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				if(a[i][j])
					for(int k=1;k<=r.m;++k)
						inc(r.a[i][k],1ll*a[i][j]*t.a[j][k]%mod);
		return r;
	}
} per,O;
struct Tree {
	int to[26],en;
} t[50];
int n,m,dot,mp[2000],fk[205];
char in[10];

Mat qkpow(int y) {
	Mat r; r.n=r.m=per.n;
	for(int i=1;i<=r.n;++i) r.a[i][i]=1;
	while(y) {
		if(y&1) r=r*per;
		per=per*per; y>>=1;
	}
	return r;
}

void ins() {
	int p=0,len;
	scanf("%s",in+1); len=strlen(in+1);
	for(int i=1;i<=len;++i) {
		int d=in[i]-'a';
		if(!t[p].to[d])
			t[p].to[d]=++dot;
		p=t[p].to[d];
	}
	t[p].en=1;
}

int dfs(int u,int v) {
	if(mp[u*bas+v]) return mp[u*bas+v];
	mp[u*bas+v]=++per.n,fk[per.n]=(t[u].en&t[v].en);
	int ids,id=per.n;
	for(int i=0;i<26;++i) {
		if(t[0].to[i]) {
			if(t[u].en and t[v].to[i]) {
				ids=dfs(t[0].to[i],t[v].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].en and t[v].en) {
				ids=dfs(t[0].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].to[i] and t[v].en) {
				ids=dfs(t[u].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
		}
		if(t[u].to[i] and t[v].to[i]) {
			ids=dfs(t[u].to[i],t[v].to[i]);
			per.a[id][ids]=1;
		}
	}
	return id;
}

int main() {
	n=read(9),m=read(9);
	for(int i=1;i<=n;++i) ins();
	for(int i=0;i<26;++i) if(t[0].to[i]) {
		dfs(t[0].to[i],t[0].to[i]);
		O.a[1][mp[t[0].to[i]*bas+t[0].to[i]]]=1;
	}
	O.m=per.m=per.n,O.n=1;
	O=O*qkpow(m-1);
	int ans=0;
	for(int i=1;i<=per.n;++i)
		if(fk[i]) inc(ans,O.a[1][i]);
	print(ans,'\n');
	return 0;
}

#include <cstdio>
#include <cstring>

#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define print(x,y) write(x),putchar(y)

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}

const int mod=998244353,bas=42;

inline void inc(int &x,int y) {
	x=(x+y>=mod)?x+y-mod:x+y;
}

struct Mat {
	int n,m,a[201][201];
	Mat() {n=m=0,memset(a,0,sizeof a);}

	Mat operator * (const Mat &t) const {
		Mat r; r.n=n,r.m=t.m;
		rep(i,1,n) rep(j,1,m)
			if(a[i][j]) rep(k,1,r.m)
				inc(r.a[i][k],1ll*a[i][j]*t.a[j][k]%mod);
		return r;
	}
} per,O;
struct Tree {
	int to[26],en;
} t[50];
int n,m,dot,mp[2000],fk[205];
char in[10];

Mat qkpow(int y) {
	Mat r; r.n=r.m=per.n;
	rep(i,1,r.n) r.a[i][i]=1;
	while(y) {
		if(y&1) r=r*per;
		per=per*per; y>>=1;
	}
	return r;
}

void ins() {
	int p=0;
	scanf("%s",in+1);
	rep(i,1,strlen(in+1)) {
		int d=in[i]-'a';
		if(!t[p].to[d])
			t[p].to[d]=++dot;
		p=t[p].to[d];
	}
	t[p].en=1;
}

int dfs(int u,int v) {
	if(mp[u*bas+v]) return mp[u*bas+v];
	mp[u*bas+v]=++per.n,fk[per.n]=(t[u].en&t[v].en);
	int ids,id=per.n;
	rep(i,0,25) {
		if(t[0].to[i]) {
			if(t[u].en and t[v].to[i]) {
				ids=dfs(t[0].to[i],t[v].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].en and t[v].en) {
				ids=dfs(t[0].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].to[i] and t[v].en) {
				ids=dfs(t[u].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
		}
		if(t[u].to[i] and t[v].to[i]) {
			ids=dfs(t[u].to[i],t[v].to[i]);
			per.a[id][ids]=1;
		}
	}
	return id;
}

int main() {
	n=read(9),m=read(9);
	rep(i,1,n) ins();
	rep(i,0,25) if(t[0].to[i]) {
		dfs(t[0].to[i],t[0].to[i]);
		O.a[1][mp[t[0].to[i]*bas+t[0].to[i]]]=1;
	}
	O.m=per.m=per.n,O.n=1;
	O=O*qkpow(m-1);
	int ans=0;
	rep(i,1,per.n)
		if(fk[i]) inc(ans,O.a[1][i]);
	print(ans,'\n');
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

#ifdef Adrian
#include "debug.h"
#else
#define debug(...) 9999
#endif

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef complex<ll> point;
#define F first
#define S second
#define ii pair<int, int>

ll mod = 998244353;
vector<vector<ll>> mul(vector<vector<ll>> a, vector<vector<ll>> b)
{
    int n = a.size();
    vector<vector<ll>> c(n, vector<ll>(n));
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
            for(int k=0; k<n; k++)
                c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % mod;
    return c;
}
vector<vector<ll>> pot(vector<vector<ll>> a, int b)
{
    int n = a.size();
    vector<vector<ll>> c(n, vector<ll>(n));
    for(int i=0; i<n; i++) c[i][i] = 1;
    for(; b>0; b>>=1)
    {
        if(b & 1) c = mul(c, a);
        a = mul(a, a);
    }
    return c;
}

int main()
{
#ifdef Adrian
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
#else
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif

    int n, m;
    cin>>n>>m;

    vector<string> v(n);
    for(auto &i:v) cin>>i;

    vector<bool> fin = {false};
    vector<vector<int>> ch;
    ch.push_back(vector<int>(26, -1));
    for(int i=0; i<n; i++)
    {
        int r = 0;
        for(auto &j:v[i])
        {
            int c = j - 'a';
            if(ch[r][c] == -1)
            {
                ch.push_back(vector<int>(26, -1));
                ch[r][c] = fin.size();
                fin.push_back(false);
            }

            r = ch[r][c];
        }
        fin[r] = true;
    }

    vector<vector<ll>> mat(1000,
               vector<ll>(1000));
    int p = 1;
    int sz = ch.size();
    vector<vector<int>> id(sz,
            vector<int>(sz, -1));
    id[0][0] = 0;
    queue<ii> q; q.push({0, 0});
    auto get = [&](int u, int v)
    {
        if(u > v) swap(u, v);
        if(id[u][v] == -1)
            id[u][v] = p++, q.push({u, v});
        return id[u][v];
    };
    while(!q.empty())
    {
        int x = q.front().F;
        int y = q.front().S;
        q.pop();

        int u = get(x, y);

        for(int t=0; t<26; t++)
        {
            int i = ch[x][t];
            int j = ch[y][t];
            if(i == -1 || j == -1) continue;

            ++mat[u][get(i, j)];
            if(fin[i]) ++mat[u][get(0, j)];
            if(fin[j]) ++mat[u][get(i, 0)];
            if(fin[i] && fin[j]) ++mat[u][0];
        }
    }
    mat.resize(p);
    for(auto &i:mat) i.resize(p);

    auto ans = pot(mat, m);
    cout<<ans[0][0]<<'\n';

    return 0;
}

/*
3 5
ababa
ab
a

2 4
ab
cd

5 100
a
aa
aaa
aaaa
aaaaa

8 3
ba
bbb
bb
aba
aab
baa
b
a

8 10
aa
ba
a
aaa
bb
aab
aba
b
 */

#include <bits/stdc++.h>
using namespace std;

#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
#define debug(...) do {cerr<<__LINE__<<" : ("#__VA_ARGS__<<") = "; Out(__VA_ARGS__); cerr<<flush;} while(0)
template <typename T> void Out(T x) {cerr<<x<<"\n";}
template <typename T,typename ...I> void Out(T x,I ...NEXT) {cerr<<x<<", "; Out(NEXT...);}

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}

const int mod=998244353,bas=42;

inline void inc(int &x,int y) {
	x=x+y;
	if(x>=mod) x=x-mod;
}

struct Mat {
	int n,m; long long a[205][205];
	Mat() {n=m=0,memset(a,0,sizeof a);}

	Mat operator * (const Mat &t) const {
		Mat r; r.n=n,r.m=t.m;
		rep(i,1,n) rep(j,1,m)
			if(a[i][j]) rep(k,1,r.m)
				r.a[i][k]=(r.a[i][k]+a[i][j]*t.a[j][k])%mod;
		return r;
	}
} per,O;
struct Tree {
	int to[26],en;
} t[50];
int n,m,dot,mp[2000],fk[205];
char in[10];

Mat qkpow(int y) {
	Mat r; r.n=r.m=per.n;
	rep(i,1,r.n) r.a[i][i]=1;
	while(y) {
		if(y&1) r=r*per;
		per=per*per; y>>=1;
	}
	return r;
}

void ins() {
	int p=0;
	scanf("%s",in+1);
	rep(i,1,strlen(in+1)) {
		int d=in[i]-'a';
		if(!t[p].to[d])
			t[p].to[d]=++dot;
		p=t[p].to[d];
	}
	t[p].en=1;
}

int dfs(int u,int v) {
	if(mp[u*bas+v]) return mp[u*bas+v];
	mp[u*bas+v]=++per.n,fk[per.n]=(t[u].en&t[v].en);
	int ids,id=per.n;
	rep(i,0,25) {
		if(t[0].to[i]) {
			if(t[u].en and t[v].to[i]) {
				ids=dfs(t[0].to[i],t[v].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].en and t[v].en) {
				ids=dfs(t[0].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].to[i] and t[v].en) {
				ids=dfs(t[u].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
		}
		if(t[u].to[i] and t[v].to[i]) {
			ids=dfs(t[u].to[i],t[v].to[i]);
			per.a[id][ids]=1;
		}
	}
	return id;
}

int main() {
	n=read(9),m=read(9);
	rep(i,1,n) ins();
	rep(i,0,25) if(t[0].to[i]) {
		dfs(t[0].to[i],t[0].to[i]);
		O.a[1][mp[t[0].to[i]*bas+t[0].to[i]]]=1;
	}
	O.m=per.m=per.n,O.n=1;
	O=O*qkpow(m-1);
	int ans=0;
	rep(i,1,per.n)
		if(fk[i]) inc(ans,O.a[1][i]);
	print(ans,'\n');
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
#define debug(...) do {cerr<<__LINE__<<" : ("#__VA_ARGS__<<") = "; Out(__VA_ARGS__); cerr<<flush;} while(0)
template <typename T> void Out(T x) {cerr<<x<<"\n";}
template <typename T,typename ...I> void Out(T x,I ...NEXT) {cerr<<x<<", "; Out(NEXT...);}

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}

const int mod=998244353,bas=42;

inline void inc(int &x,int y) {
	x=x+y;
	if(x>=mod) x=x-mod;
}

struct Mat {
	int n,m; long long a[205][205];
	Mat() {n=m=0,memset(a,0,sizeof a);}

	Mat operator * (const Mat &t) const {
		Mat r; r.n=n,r.m=t.m;
		rep(i,1,n) rep(j,1,m)
			if(a[i][j]) rep(k,1,r.m)
				r.a[i][k]=(r.a[i][k]+a[i][j]*t.a[j][k])%mod;
		return r;
	}
} per,O;
struct Tree {
	int to[26],en;
} t[50];
int n,m,dot,mp[2000],fk[205];
char in[10];

Mat qkpow(int y) {
	Mat r; r.n=r.m=per.n;
	rep(i,1,r.n) r.a[i][i]=1;
	while(y) {
		if(y&1) r=r*per;
		per=per*per; y>>=1;
	}
	return r;
}

void ins() {
	int p=0;
	scanf("%s",in+1);
	rep(i,1,strlen(in+1)) {
		int d=in[i]-'a';
		if(!t[p].to[d])
			t[p].to[d]=++dot;
		p=t[p].to[d];
	}
	t[p].en=1;
}

int dfs(int u,int v) {
	if(mp[u*bas+v]) return mp[u*bas+v];
	mp[u*bas+v]=++per.n,fk[per.n]=(t[u].en&t[v].en);
	int ids,id=per.n;
	rep(i,0,25) {
		if(t[0].to[i]) {
			if(t[u].en and t[v].to[i]) {
				ids=dfs(t[0].to[i],t[v].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].en and t[v].en) {
				ids=dfs(t[0].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].to[i] and t[v].en) {
				ids=dfs(t[u].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
		}
		if(t[u].to[i] and t[v].to[i]) {
			ids=dfs(t[u].to[i],t[v].to[i]);
			per.a[id][ids]=1;
		}
	}
	return id;
}

int main() {
	n=read(9),m=read(9);
	rep(i,1,n) ins();
	rep(i,0,25) if(t[0].to[i]) {
		dfs(t[0].to[i],t[0].to[i]);
		O.a[1][mp[t[0].to[i]*bas+t[0].to[i]]]=1;
	}
	O.m=per.m=per.n,O.n=1;
	O=O*qkpow(m-1);
	int ans=0;
	rep(i,1,per.n)
		if(fk[i]) inc(ans,O.a[1][i]);
	print(ans,'\n');
	return 0;
} // OOO

#include<bits/stdc++.h>
using namespace std;

#define INF 1234567890
#define ll long long
#define MOD 998244353
#define mat array<array<ll, 208>, 208>

mat mul(mat &A, mat &B)
{
	mat ret;
	for(int i=0; i<208; i++)
		for(int j=0; j<208; j++)
			ret[i][j] = 0;
	// block
	const int SM = 8;
	for(int i=0; i<208; i+=SM)
		for(int k=0; k<208; k+=SM)
			for(int j=0; j<208; j+=SM)
				for(int ii=i; ii<i+SM; ii++)
					for(int kk=k; kk<k+SM; kk++)
						for(int jj=j; jj<j+SM; jj++)
							ret[ii][jj] += A[ii][kk] * B[kk][jj], ret[ii][jj] %= MOD;
	return ret;
}

mat pw(mat A, int n)
{
	mat ret;
	for(int i=0; i<208; i++)
		for(int j=0; j<208; j++)
			ret[i][j] = 0;
	for(int i=0; i<208; i++)
		ret[i][i] = 1;
	while(n)
	{
		if (n&1) ret = mul(ret, A);
		A = mul(A, A);
		n>>=1;
	}
	return ret;
}

struct Node {
	int g[26];
	int cnt;
	bool chk;
};

int N, M, P;
Node trie[41];
mat A;

void Insert(int n, int i, string &s)
{
	trie[n].cnt++;
	if (i == s.size())
	{
		trie[n].chk = true;
		return;
	}
	if (trie[n].g[s[i]-'a'] == 0) trie[n].g[s[i]-'a'] = ++P;
	Insert(trie[n].g[s[i]-'a'], i+1, s);
}

void Search(int n, int m, int k, int root)
{
	if (k && trie[n].chk && trie[m].chk) // 동시에 끝내기
	{
		// dp[i][root] += dp[i-k][0]
		// (i-k, j)라면 (k-1)*P+j로 놓자.
		A[root][(k-1)*P+0]++;
	}
	if (k && (trie[n].cnt - !!trie[n].chk >= 1) && trie[m].chk) // m만 끝내기
	{
		// dp[i][root] += dp[i-k][m]
		A[root][(k-1)*P+n]++;
	}
	if (k && trie[n].chk && (trie[m].cnt - !!trie[m].chk >= 1)) // n만 끝내기
	{
		// dp[i][root] += dp[i-k][m]
		A[root][(k-1)*P+m]++;
	}
	for(int i=0; i<26; i++)
		if (trie[n].g[i] && trie[m].g[i])
			Search(trie[n].g[i], trie[m].g[i], k+1, root);
}

int main()
{
	ios::sync_with_stdio(0); cin.tie(0);
	cin.exceptions(ios::badbit | ios::failbit);
	cin >> N >> M;
	for(int i=0; i<N; i++)
	{
		string s;
		cin >> s;
		reverse(s.begin(), s.end()); // suffix trie
		Insert(0, 0, s);
	}
	P++; // [0, P)
	// 상태 전이 만들기 (208 * 208 크기 행렬)
	for(int n=0; n<P; n++)
		Search(n, 0, 0, n);
	for(int k=1; k<=4; k++)
		for(int j=0; j<P; j++)
			A[k*P+j][(k-1)*P+j]++;
	A = pw(A, M);
	// base case : dp[0][0] = 1
	// res : dp[M][0]
	ll res = A[0][0];
	cout << res << "\n";
	return 0;
}

#include<bits/stdc++.h>
using namespace std;

#define INF 1234567890
#define ll long long
#define MOD 998244353
#define mat array<array<ll, 205>, 205>

mat mul(mat &A, mat &B)
{
	mat ret;
	for(int i=0; i<205; i++)
		for(int j=0; j<205; j++)
			ret[i][j] = 0;

	// block
	const int SM = 8;
	for(int i=0; i<205; i+=SM)
		for(int k=0; k<205; k+=SM)
			for(int j=0; j<205; j+=SM)
				for(int ii=i; ii<min(i+SM,205); ii++)
					for(int kk=k; kk<min(k+SM,205); kk++)
						for(int jj=j; jj<min(j+SM,205); jj++)
							ret[ii][jj] += A[ii][kk] * B[kk][jj], ret[ii][jj] %= MOD;
	return ret;
}

mat pw(mat A, int n)
{
	mat ret;
	for(int i=0; i<205; i++)
		for(int j=0; j<205; j++)
			ret[i][j] = 0;
	for(int i=0; i<205; i++)
		ret[i][i] = 1;
	while(n)
	{
		if (n&1) ret = mul(ret, A);
		A = mul(A, A);
		n>>=1;
	}
	return ret;
}

struct Node {
	int g[26];
	int cnt;
	bool chk;
};

int N, M, P;
Node trie[41];
mat A;

void Insert(int n, int i, string &s)
{
	trie[n].cnt++;
	if (i == s.size())
	{
		trie[n].chk = true;
		return;
	}
	if (trie[n].g[s[i]-'a'] == 0) trie[n].g[s[i]-'a'] = ++P;
	Insert(trie[n].g[s[i]-'a'], i+1, s);
}

void Search(int n, int m, int k, int root)
{
	if (k && trie[n].chk && trie[m].chk) // 동시에 끝내기
	{
		// dp[i][root] += dp[i-k][0]
		// (i-k, j)라면 (k-1)*P+j로 놓자.
		A[root][(k-1)*P+0]++;
	}
	if (k && (trie[n].cnt - !!trie[n].chk >= 1) && trie[m].chk) // m만 끝내기
	{
		// dp[i][root] += dp[i-k][m]
		A[root][(k-1)*P+n]++;
	}
	if (k && trie[n].chk && (trie[m].cnt - !!trie[m].chk >= 1)) // n만 끝내기
	{
		// dp[i][root] += dp[i-k][m]
		A[root][(k-1)*P+m]++;
	}
	for(int i=0; i<26; i++)
		if (trie[n].g[i] && trie[m].g[i])
			Search(trie[n].g[i], trie[m].g[i], k+1, root);
}

int main()
{
	ios::sync_with_stdio(0); cin.tie(0);
	cin.exceptions(ios::badbit | ios::failbit);
	cin >> N >> M;
	for(int i=0; i<N; i++)
	{
		string s;
		cin >> s;
		reverse(s.begin(), s.end()); // suffix trie
		Insert(0, 0, s);
	}
	P++; // [0, P)
	// 상태 전이 만들기 (205 * 205 크기 행렬)
	for(int n=0; n<P; n++)
		Search(n, 0, 0, n);
	for(int k=1; k<=4; k++)
		for(int j=0; j<P; j++)
			A[k*P+j][(k-1)*P+j]++;
	A = pw(A, M);
	// base case : dp[0][0] = 1
	// res : dp[M][0]
	ll res = A[0][0];
	cout << res << "\n";
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 8 + 5;
const int MAXL = 5 + 5;
const int MAXP = 40 + 5;
const int mod = 998244353;

inline void add_mod(int &a,int b){ a+=b; if(a>=mod) a-=mod;}

const int N = 2e2;

struct Matrix
{
	int a[N][N];
	Matrix(void){ memset(a,0,sizeof(a));}
	inline int* operator [] (const int x){ return a[x];}
	inline const int* operator [] (const int x) const { return a[x];}
	inline void to_unit(void){ for(int i=0; i<N; ++i) a[i][i] = 1;}
	inline Matrix operator * (const Matrix &b) const
	{
		Matrix res;
		for(int k=0; k<N; ++k)
			for(int i=0; i<N; ++i)
				for(int j=0; j<N; ++j)
					res[i][j] = (res[i][j] + (ll)a[i][k] * b[k][j]) %mod;
		return res;
	}
};

inline Matrix pw(Matrix a,int b)
{
	Matrix res; res.to_unit();
	while(b)
	{
		if(b&1) res=res*a;
		a=a*a; b>>=1;
	}
	return res;
}

struct Trie
{
	int son[MAXP][30], leaf[MAXP], pcnt;
	Trie(void): pcnt(1) {}
	inline int size(void) const { return pcnt;}
	inline int* operator [] (const int x){ return son[x];}
	inline const int* operator [] (const int x) const { return son[x];}
	inline void insert(const char s[])
	{
		int u = 1;
		for(int i=1; s[i]; ++i)
		{
			if(!son[u][s[i] - 'a']) son[u][s[i] - 'a'] = ++pcnt;
			u = son[u][s[i] - 'a'];
		}
		leaf[u] = 1;
	};
}tree;

char s[MAXN][MAXL];

vector<pii> g[MAXP][MAXP];
int pid[MAXP][MAXP], tot = 0;

void dfs_pid(int u,int v)
{
	if(pid[u][v]) return;
	pid[u][v] = ++tot;
	for(int i=0; i<(int)g[u][v].size(); ++i)
		dfs_pid(g[u][v][i].first, g[u][v][i].second);
}

int main(void)
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; ++i) scanf("%s",s[i]+1);

	for(int i=1; i<=n; ++i) tree.insert(s[i]);

	for(int u=1; u<=(int)tree.size(); ++u)
		for(int v=u; v<=(int)tree.size(); ++v)
			for(int k=0; k<26; ++k)
			{
				int uu = tree[u][k], vv = tree[v][k];
				if(!uu || !vv) continue;
				if(uu > vv) swap(uu,vv);

				g[u][v].push_back(make_pair(uu,vv));

				if(tree.leaf[uu]) g[u][v].push_back(make_pair(1,vv));
				if(tree.leaf[vv]) g[u][v].push_back(make_pair(1,uu));

				if(tree.leaf[uu] && tree.leaf[vv])
					g[u][v].push_back(make_pair(1,1));
			}

	dfs_pid(1,1);

	Matrix mat;
	for(int u=1; u<=(int)tree.size(); ++u)
		for(int v=1; v<=(int)tree.size(); ++v) if(pid[u][v])
			for(int i=0; i<(int)g[u][v].size(); ++i)
			{
				int uu = g[u][v][i].first, vv = g[u][v][i].second;
				if(!pid[uu][vv]) continue;

				add_mod(mat[pid[uu][vv] - 1][pid[u][v] - 1], 1);
			}

	printf("%d",pw(mat,m)[0][0]);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;

#define INF 1234567890
#define ll long long
#define MOD 998244353
#define mat array<array<ll, 205>, 205>

mat mul(mat &A, mat &B)
{
	mat ret;
	for(int i=0; i<205; i++)
		for(int j=0; j<205; j++)
			ret[i][j] = 0;
	for(int i=0; i<205; i++)
		for(int k=0; k<205; k++)
		{
			ll tmp = A[i][k];
			for(int j=0; j<205; j++)
				ret[i][j] += tmp * B[k][j], ret[i][j] %= MOD; // i k j
		}
	return ret;
}

mat pw(mat A, int n)
{
	mat ret;
	for(int i=0; i<205; i++)
		for(int j=0; j<205; j++)
			ret[i][j] = 0;
	for(int i=0; i<205; i++)
		ret[i][i] = 1;
	while(n)
	{
		if (n&1) ret = mul(ret, A);
		A = mul(A, A);
		n>>=1;
	}
	return ret;
}

struct Node {
	int g[26];
	int cnt;
	bool chk;
};

int N, M, P;
Node trie[41];
mat A;

void Insert(int n, int i, string &s)
{
	trie[n].cnt++;
	if (i == s.size())
	{
		trie[n].chk = true;
		return;
	}
	if (trie[n].g[s[i]-'a'] == 0) trie[n].g[s[i]-'a'] = ++P;
	Insert(trie[n].g[s[i]-'a'], i+1, s);
}

void Search(int n, int m, int k, int root)
{
	if (k && trie[n].chk && trie[m].chk) // 동시에 끝내기
	{
		// dp[i][root] += dp[i-k][0]
		// (i-k, j)라면 (k-1)*P+j로 놓자.
		A[root][(k-1)*P+0]++;
	}
	if (k && (trie[n].cnt - !!trie[n].chk >= 1) && trie[m].chk) // m만 끝내기
	{
		// dp[i][root] += dp[i-k][m]
		A[root][(k-1)*P+n]++;
	}
	if (k && trie[n].chk && (trie[m].cnt - !!trie[m].chk >= 1)) // n만 끝내기
	{
		// dp[i][root] += dp[i-k][m]
		A[root][(k-1)*P+m]++;
	}
	for(int i=0; i<26; i++)
		if (trie[n].g[i] && trie[m].g[i])
			Search(trie[n].g[i], trie[m].g[i], k+1, root);
}

int main()
{
	ios::sync_with_stdio(0); cin.tie(0);
	cin.exceptions(ios::badbit | ios::failbit);
	cin >> N >> M;
	for(int i=0; i<N; i++)
	{
		string s;
		cin >> s;
		reverse(s.begin(), s.end()); // suffix trie
		Insert(0, 0, s);
	}
	P++; // [0, P)
	// 상태 전이 만들기 (205 * 205 크기 행렬)
	for(int n=0; n<P; n++)
		Search(n, 0, 0, n);
	for(int k=1; k<=4; k++)
		for(int j=0; j<P; j++)
			A[k*P+j][(k-1)*P+j]++;
	A = pw(A, M);
	// base case : dp[0][0] = 1
	// res : dp[M][0]
	ll res = A[0][0];
	cout << res << "\n";
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 8 + 5;
const int MAXL = 5 + 5;
const int mod = 998244353;

inline void add_mod(int &a,int b){ a+=b; if(a>=mod) a-=mod;}

const int M = 8 * 4 + 1;
const int N = 5 * M;

struct Matrix
{
	int a[N][N];
	Matrix(void){ clear();}
	inline void clear(void){ memset(a,0,sizeof(a));}
	inline int* operator [] (const int x){ return a[x];}
	inline const int* operator [] (const int x) const { return a[x];}
	inline Matrix operator * (const Matrix &b) const
	{
		Matrix res;
		for(int k=0; k<N; ++k)
			for(int i=0; i<N; ++i)
				for(int j=0; j<N; ++j)
					res[i][j] = (res[i][j] + (ll)a[i][k] * b[k][j]) %mod;
		return res;
	}
};

inline int get_id(int x,int y,int z)
{
	return M * (x - 1) + (y? (y - 1) * 4 + z: 0);
}
inline int get_id(int x,int yz){ return M * (x-1) + yz;}

char s[MAXN][MAXL];
int len[MAXN];

inline bool is_ok(int x,int l,int y)
{
	for(int i=len[x]-l+1,j=1; i<=len[x] && j<=len[y]; ++i,++j)
		if(s[x][i] != s[y][j]) return 0;
	return 1;
}

int main(void)
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; ++i)
		scanf("%s",s[i]+1), len[i] = strlen(s[i]+1);

	Matrix mat;
	for(int i=2; i<=5; ++i)
		for(int j=0; j<M; ++j)
			mat[get_id(i-1,j)][get_id(i,j)] = 1;
	for(int i=1; i<=n; ++i)
		for(int j=1; j<len[i]; ++j)
			for(int k=1; k<=n; ++k) if(is_ok(i,j,k))
			{
				int more = min(j, len[k]), ii, jj;
				if(j == len[k]) ii = jj = 0;
				else if(j < len[k]) ii = k, jj = len[k] - j;
				else ii = i, jj = j - len[k];

				add_mod(mat[get_id(5, ii, jj)][get_id(5-more+1, i, j)], 1);
			}
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=n; ++j) if(is_ok(i,len[i],j))
		{
			int more = min(len[i], len[j]), ii, jj;
			if(len[i] == len[j]) ii = jj = 0;
			else if(len[i] < len[j]) ii = j, jj = len[j] - len[i];
			else ii = i, jj = len[i] - len[j];

			add_mod(mat[get_id(5, ii, jj)][get_id(5-more+1, 0)], 1);
		}

	static Matrix res;
	for(int i=0; i<N; ++i) res[i][i] = 1;
	while(m)
	{
		if(m&1) res=res*mat;
		mat=mat*mat; m>>=1;
	}

	printf("%d",res[get_id(5,0)][get_id(5,0)]);
	return 0;
}

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <queue>
using namespace std;
#define endl '\n'
#define ll long long
#define pi pair<int, int>
#define f first
#define s second

const int mod = 998244353;
const int mxk = 41, w = 26, mxz = 200;
int n, m, k, z;
int d[mxk];
int tr[mxk][w];
int f[mxk][mxk];
ll a[mxz][mxz], b[mxz][mxz];
queue<pi> q;

void mul(ll x[mxz][mxz], ll y[mxz][mxz]){
	ll ret[mxz][mxz];
	for(int i = 0; i < z; i++)
	for(int j = 0; j < z; j++){
		ret[i][j] = 0;
		for(int l = 0; l < z; l++){
			(ret[i][j] += x[i][l] * y[l][j]) %= mod;
		}
	}
	memcpy(x, ret, sizeof(ret));
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;

	for(int i  = 0; i < n; i++){
		string s;
		cin >> s;
		int x = 0;
		for(char &j : s){
			j -= 'a';
			if(!tr[x][j]) tr[x][j] = ++k;
			x = tr[x][j];
		}
		d[x] = 1;
	}

	memset(f, -1, sizeof(f));
	a[z][z] = 1, f[0][0] = z++;
	q.push({0, 0});
	while(!q.empty()){
		pi c = q.front();
		q.pop();
 		for(int i = 0; i < w; i++) if(tr[c.f][i] && tr[c.s][i])
		for(int j = 0; j <= d[tr[c.f][i]]; j++)
		for(int l = 0; l <= d[tr[c.s][i]]; l++){
			pi p = {!j * tr[c.f][i], !l * tr[c.s][i]};
			if(p.f > p.s) swap(p.f, p.s);
			if(!~f[p.f][p.s]) a[z][z] = 1, f[p.f][p.s] = z++, q.push(p);
			b[f[c.f][c.s]][f[p.f][p.s]]++;
		}
	}

	for(int i = m; i; i >>= 1){
		if(i & 1) mul(a, b);
		mul(b, b);
	}

	cout << a[0][0] << endl;

	return 0;
}

#include<bits/stdc++.h>
using namespace std;
namespace my_std{
	#define ll long long
	#define bl bool
	ll my_pow(ll a,ll b,ll mod){
		ll res=1;
		if(!b) return 1;
		while(b){
			if(b&1) res=(res*a)%mod;
			a=(a*a)%mod;
			b>>=1;
		}
		return res;
	}
	ll qpow(ll a,ll b){
		ll res=1;
		if(!b) return 1;
		while(b){
			if(b&1) res*=a;
			a*=a;
			b>>=1;
		}
		return res;
	}
	#define db double
	#define pf printf
	#define pc putchar
	#define fr(i,x,y) for(register ll i=(x);i<=(y);i++)
	#define pfr(i,x,y) for(register ll i=(x);i>=(y);i--)
	#define go(u) for(ll i=head[u];i;i=e[i].nxt)
	#define enter pc('\n')
	#define space pc(' ')
	#define fir first
	#define sec second
	#define MP make_pair
	#define il inline
	#define inf 8e18
	#define random(x) rand()*rand()%(x)
	#define inv(a,mod) my_pow((a),(mod-2),(mod))
	il ll read(){
		ll sum=0,f=1;
		char ch=0;
		while(!isdigit(ch)){
			if(ch=='-') f=-1;
			ch=getchar();
		}
		while(isdigit(ch)){
			sum=sum*10+(ch^48);
			ch=getchar();
		}
		return sum*f;
	}
	il void write(ll x){
		if(x<0){
			x=-x;
			pc('-');
		}
		if(x>9) write(x/10);
		pc(x%10+'0');
	}
	il void writeln(ll x){
		write(x);
		enter;
	}
	il void writesp(ll x){
		write(x);
		space;
	}
}
using namespace my_std;
#define mod 998244353
ll n,m,ch[55][26],rt=1,tot=1,mp[55][55],cnt=0;
bl ed[55];
char s[11];
struct matrix{
	ll a[220][220];
	void clr(){
		fr(i,1,cnt) fr(j,1,cnt) a[i][j]=0;
	}
	void one(){
		clr();
		fr(i,1,cnt) a[i][i]=1;
	}
	matrix operator*(const matrix &x){
		matrix res;
		res.clr();
		fr(i,1,cnt) fr(j,1,cnt) fr(k,1,cnt) res.a[i][j]=(res.a[i][j]+a[i][k]*x.a[k][j]%mod)%mod;
		return res;
	}
}P,A;
ll dfs(ll x,ll y){
	if(x>y) swap(x,y);
	if(mp[x][y]) return mp[x][y];
	mp[x][y]=++cnt;
	fr(i,0,25){
		if(!ch[x][i]||!ch[y][i]) continue;
		A.a[mp[x][y]][dfs(ch[x][i],ch[y][i])]++;
		if(ed[ch[x][i]]) A.a[mp[x][y]][dfs(rt,ch[y][i])]++;
		if(ed[ch[y][i]]) A.a[mp[x][y]][dfs(ch[x][i],rt)]++;
		if(ed[ch[x][i]]&&ed[ch[y][i]]) A.a[mp[x][y]][1]++;
	}
	return mp[x][y];
}
matrix mpow(matrix x,ll y){
	matrix res;
	res.one();
	while(y){
		if(y&1) res=res*x;
		x=x*x;
		y>>=1;
	}
	return res;
}
int main(){
	n=read();
	m=read();
	fr(i,1,n){
		scanf("%s",s+1);
		ll len=strlen(s+1),x=rt;
		fr(j,1,len){
			if(!ch[x][s[j]-'a']) ch[x][s[j]-'a']=++tot;
			x=ch[x][s[j]-'a'];
		}
		ed[x]=1;
	}
	dfs(rt,rt);
	P.a[1][1]=1;
	P=P*mpow(A,m);
	write(P.a[1][1]);
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <iomanip>
#define endl '\n'
#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ldb;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef pair<LL, int> pli;
typedef pair<int, long> pil;
const int INF = 0x3f3f3f3f;
inline int read(){
    register int x; register char c(getchar()); register bool k;
    while((c < '0' || c > '9') && c ^ '-') if((c = getchar()) == EOF) exit(0);
    if(c ^ '-') x = c & 15, k = 1; else x = 0, k = 0;
    while(c = getchar(), c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c & 15);
    return k ? x : -x;
}

const int maxn = 100, mod = 998244353;
char s[10];
int trie[maxn][26], tot;
bool endp[maxn];

void insert(char *s){
    int len = strlen(s), cur = 0;
    for(int i = 0; i < len; i++){
        if(!trie[cur][s[i] - 'a']) trie[cur][s[i] - 'a'] = ++tot;
        cur = trie[cur][s[i] - 'a'];
    }
    endp[cur] = 1;
}

typedef vector<int> vec;
typedef vector<vec> mat;

// 计算矩阵A*矩阵B，元素对mod取模
mat mod_mul(mat &A, mat &B){
    mat C(A.size(), vec(B[0].size()));
    for(int i = 0; i < A.size(); i++){
        for(int k = 0; k < B.size(); k++){
            if(A[i][k])
            for(int j = 0; j < B[0].size(); j++){
                if(B[k][j])
                C[i][j] = (C[i][j] + ((LL)A[i][k] * B[k][j]) % mod) % mod;
            }
        }
    }
    return C;
}

// 计算矩阵A的n次方
mat mod_pow(mat A, LL n){
    mat B(A.size(), vec(A.size()));
    for(int i =0; i < A.size(); i++) B[i][i] = 1;
    while(n > 0){
        if(n & 1) B = mod_mul(B, A);
        A = mod_mul(A, A);
        n >>= 1;
    }
    return B;
}

queue<pii> que;
map<pii, int> mp;
int cnt;
int get_id(pii p){
    if(p.first > p.second) swap(p.first, p.second);
    if(mp.count(p)) return mp[p];
    mp[p] = cnt++;
    que.push(p);
    return cnt - 1;
}

int main(){
    int n = read(), m = read();
    for(int i = 1; i <= n; i++){
        scanf("%s", s);
        insert(s);
    }
    mat M = mat(140, vec(140));
    get_id(pii(0, 0));
    while(que.size()){
        pii p = que.front(); que.pop();
        int p1 = p.first, p2 = p.second, id = get_id(p);
        for(int i = 0; i < 26; i++){
            int tp1 = trie[p1][i], tp2 = trie[p2][i];
            if(!tp1 || !tp2) continue;
            M[id][get_id(pii(tp1, tp2))]++;
            if(endp[tp1]) M[id][get_id(pii(0, tp2))]++;
            if(endp[tp2]) M[id][get_id(pii(tp1, 0))]++;
            if(endp[tp1] && endp[tp2]) M[id][get_id(pii(0, 0))]++;
        }
    }
    /*for(int i = 0; i < 15; i++){
        for(int j = 0; j < 15; j++)
            cout << M[i][j] << ' ';
        cout << endl;
    }*/
    mat ans = mod_pow(M, m);
    cout << ans[0][0] << endl;
    return 0;
}

#include <bits/stdc++.h>
#define res register int
#define pi pair<int, int>
#define fi first
#define se second
#define N 160
#define ll long long
#define mod 998244353
using namespace std;
int n;
ll m;
map<pi,int> Map;
inline int read(){
    res w=0,X=0;register char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch)){X=(X<<1)+(X<<3)+(ch^48);ch=getchar();}
    return w?-X:X;
}
struct Mat{
	int M[N][N];
	Mat(){
	   memset(M, 0, sizeof(M));
//	   for(res i = 0; i < N; i++)
//	     M[i][i] = 1;
	}
	Mat(int val){
	   memset(M, 0, sizeof(M));
	   for(res i = 0; i < N; i++)
	     M[i][i] = val;
	}
	Mat operator * (const Mat A){
		Mat ret;
		for(res i = 0; i < N; i++)
		  for(res j = 0; j < N; j++)
		    for(res k = 0; k < N; k++)
		      ret.M[i][j] = (ret.M[i][j] + 1LL * M[i][k] * A.M[k][j] % mod) % mod;
		return ret;
	}
}Ans;
namespace T{
	bool End[N];
	int son[N][26], tot = 0, ID = 0;
	queue<pi> l;
	inline int getid(res fi, res se){
		if(fi > se) swap(fi, se);
		if(fi == se && fi == 0) return 0;
		if(Map[make_pair(fi, se)]) return Map[make_pair(fi, se)];
		l.push(make_pair(fi, se));
		return Map[make_pair(fi, se)] = ++ID;
	}
	inline void add(string s){
		res n = s.size(), now = 0;
		for(res i = 0; i < n; i++){
			res c = s[i] - 'a';
			if(!son[now][c]) son[now][c] = ++tot;
			now = son[now][c];
		}
		End[now] = 1;
	}
	inline void init(){
		l.push(make_pair(0, 0));
		while(!l.empty()){
			pi now = l.front();
			l.pop();
			for(res i = 0; i < 26; i++)
			  if(son[now.fi][i] && son[now.se][i]){
			    Ans.M[getid(now.fi, now.se)][getid(son[now.fi][i], son[now.se][i])]++;
			    if(End[son[now.fi][i]]) Ans.M[getid(now.fi, now.se)][getid(0, son[now.se][i])]++;
			    if(End[son[now.se][i]]) Ans.M[getid(now.fi, now.se)][getid(son[now.fi][i], 0)]++;
			    if(End[son[now.fi][i]] && End[son[now.se][i]]) Ans.M[getid(now.fi, now.se)][0]++;
		      }
		    //printf("%d %d\n", now.fi, now.se);
		}
	}
}
inline Mat quickpow(Mat A, ll num){
	Mat ret(1);
	for(; num; num >>= 1LL, A = A * A)
	  if(num & 1LL)
	    ret = ret * A;
	return ret;
}
int main(){
	n = read();
	cin >> m;
	for(res i = 1; i <= n; i++){
		string s;
		cin >> s;
		T::add(s);
	}
	T::init();
	printf("%d\n", quickpow(Ans, m).M[0][0]);
	return 0;
}
//[i][j] * [j][k] = [i][k]

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <iomanip>
#define endl '\n'
#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ldb;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef pair<LL, int> pli;
typedef pair<int, long> pil;
const int INF = 0x3f3f3f3f;
inline int read(){
    register int x; register char c(getchar()); register bool k;
    while((c < '0' || c > '9') && c ^ '-') if((c = getchar()) == EOF) exit(0);
    if(c ^ '-') x = c & 15, k = 1; else x = 0, k = 0;
    while(c = getchar(), c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c & 15);
    return k ? x : -x;
}

const int maxn = 100, mod = 998244353;
char s[10];
int trie[maxn][26], tot;
bool endp[maxn];

void insert(char *s){
    int len = strlen(s), cur = 0;
    for(int i = 0; i < len; i++){
        if(!trie[cur][s[i] - 'a']) trie[cur][s[i] - 'a'] = ++tot;
        cur = trie[cur][s[i] - 'a'];
    }
    endp[cur] = 1;
}

typedef vector<int> vec;
typedef vector<vec> mat;

// 计算矩阵A*矩阵B，元素对mod取模
mat mod_mul(mat &A, mat &B){
    mat C(A.size(), vec(B[0].size()));
    for(int i = 0; i < A.size(); i++){
        for(int k = 0; k < B.size(); k++){
            if(A[i][k])
            for(int j = 0; j < B[0].size(); j++){
                if(B[k][j])
                C[i][j] = (C[i][j] + ((LL)A[i][k] * B[k][j]) % mod) % mod;
            }
        }
    }
    return C;
}

// 计算矩阵A的n次方
mat mod_pow(mat A, LL n){
    mat B(A.size(), vec(A.size()));
    for(int i =0; i < A.size(); i++) B[i][i] = 1;
    while(n > 0){
        if(n & 1) B = mod_mul(B, A);
        A = mod_mul(A, A);
        n >>= 1;
    }
    return B;
}

queue<pii> que;
map<pii, int> mp;
int cnt;
int get_id(pii p){
    if(p.first > p.second) swap(p.first, p.second);
    if(mp.count(p)) return mp[p];
    mp[p] = cnt++;
    que.push(p);
    return cnt - 1;
}

int main(){
    int n = read(), m = read();
    for(int i = 1; i <= n; i++){
        scanf("%s", s);
        insert(s);
    }
    mat M = mat(150, vec(150));
    get_id(pii(0, 0));
    while(que.size()){
        pii p = que.front(); que.pop();
        int p1 = p.first, p2 = p.second, id = get_id(p);
        for(int i = 0; i < 26; i++){
            int tp1 = trie[p1][i], tp2 = trie[p2][i];
            if(!tp1 || !tp2) continue;
            M[id][get_id(pii(tp1, tp2))]++;
            if(endp[tp1]) M[id][get_id(pii(0, tp2))]++;
            if(endp[tp2]) M[id][get_id(pii(tp1, 0))]++;
            if(endp[tp1] && endp[tp2]) M[id][get_id(pii(0, 0))]++;
        }
    }
    /*for(int i = 0; i < 15; i++){
        for(int j = 0; j < 15; j++)
            cout << M[i][j] << ' ';
        cout << endl;
    }*/
    mat ans = mod_pow(M, m);
    cout << ans[0][0] << endl;
    return 0;
}

//Author: Xzirium
//Time and Date: 22:09:20  06 May 2021

//Optional FAST
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2,tune=native")

//Required Libraries

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

//Required namespaces

using namespace std;
using namespace __gnu_pbds;

//Required defines

#define endl '\n'

#define READ(X) cin>>X;
#define READV(X) long long X; cin>>X;
#define READAR(A,N) long long A[N]; for(long long i=0;i<N;i++) {cin>>A[i];}
#define rz(A,N) A.resize(N);
#define sz(X) (long long)(X.size())
#define pb push_back
#define pf push_front
#define fi first
#define se second
#define FORI(a,b,c) for(long long a=b;a<c;a++)
#define FORD(a,b,c) for(long long a=b;a>c;a--)

//Required typedefs

template <typename T> using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
template <typename T> using ordered_set1 = tree<T,null_type,greater<T>,rb_tree_tag,tree_order_statistics_node_update>;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;

//Required Constants

const long long inf=(long long)1e18;
const long long MOD=(long long)(998244353);
const long long INIT=(long long)(1e6+1);
const long double PI=3.14159265358979;

// Required random number generators

// mt19937 gen_rand_int(chrono::steady_clock::now().time_since_epoch().count());
// mt19937_64 gen_rand_ll(chrono::steady_clock::now().time_since_epoch().count());

//Required Functions

ll power(ll b, ll e)
{
    ll r = 1ll;
    for(; e > 0; e /= 2, (b *= b) %= MOD)
        if(e % 2) (r *= b) %= MOD;
    return r;
}
ll modInverse(ll a)
{
   return power(a,MOD-2);

}

//Work
struct trie_node
{
    bool acceptor=false;
    ll child[26]={0};
    trie_node(bool ok=false)
    {
        memset(child,-1,sizeof(child));
        if(ok)
        {
            acceptor=true;
        }
    }
};
vector<trie_node> Keywords(1,trie_node(true));

void keyword_entry(string S)
{
    ll curr=0;
    ll N=S.length();
    FORI(i,0,N)
    {
        ll nxt=Keywords[curr].child[(ll)S[i]-(ll)'a'];
        if(nxt!=-1)
        {
            curr=nxt;
        }
        else
        {
            nxt=Keywords.size();
            Keywords[curr].child[(ll)S[i]-(ll)'a']=nxt;
            Keywords.pb(trie_node());
        }
        curr=nxt;
    }
    Keywords[curr].acceptor=true;
}

vector<vector<ll>> matrix_multiply(vector<vector<ll>> &A,vector<vector<ll>> &B)
{
    vector<vector<ll>> C(161,vector<ll>(161,0));
    FORI(i,0,161)
    {
        FORI(j,0,161)
        {
            FORI(k,0,161)
            {
                C[i][j]+=(A[i][k]*B[k][j])%MOD;
                if(C[i][j]>=MOD)
                {
                    C[i][j]-=MOD;
                }
            }
        }
    }
    return C;
}

vector<vector<ll>> mat_expo(vector<vector<ll>> mat,ll e)
{
    vector<vector<ll>> R(161,vector<ll>(161,0));
    FORI(i,0,161)
    {
        R[i][i]=1;
    }
    for(; e > 0; e /= 2, mat=matrix_multiply(mat,mat))
        if(e % 2) R=matrix_multiply(R,mat);

    return R;
}
map<pll,ll> found;

int main()
{
    #ifndef ONLINE_JUDGE
    if (fopen("INPUT.txt", "r"))
    {
        freopen ("INPUT.txt" , "r" , stdin);
        //freopen ("OUTPUT.txt" , "w" , stdout);
    }
    #endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    clock_t clk;
    clk = clock();
//-----------------------------------------------------------------------------------------------------------//

    READV(N);
    READV(M);
    FORI(i,0,N)
    {
        string S;
        cin>>S;
        keyword_entry(S);
    }
    vector<vector<ll>> matrix(161,vector<ll>(161,0));
    deque<pll> bfs;
    auto finder=[&](pll X)
    {
        if(X.se<X.fi)
        {
            swap(X.fi,X.se);
        }
        if(found.count(X)==0)
        {
            ll val=found.size();
            found[X]=val;
            bfs.push_back(X);
        }
        return found[X];
    };
    ll st=finder({0,0});
    while (bfs.size())
    {
        auto u=bfs.front();
        bfs.pop_front();
        ll x=finder(u);
        FORI(i,0,26)
        {
            pll v={Keywords[u.fi].child[i],Keywords[u.se].child[i]};
            if(v.fi!=-1 && v.se!=-1)
            {
                matrix[finder(v)][x]++;
                if(Keywords[v.fi].acceptor)
                {
                    matrix[finder({0,v.se})][x]++;
                }
                if(Keywords[v.se].acceptor)
                {
                    matrix[finder({v.fi,0})][x]++;
                }
                if(Keywords[v.fi].acceptor && Keywords[v.se].acceptor)
                {
                    matrix[st][x]++;
                }
            }
        }
    }

    matrix=mat_expo(matrix,M);
    cout<<matrix[st][st]<<endl;

//-----------------------------------------------------------------------------------------------------------//

    clk = clock() - clk;
    cerr << fixed << setprecision(6) << "Time: " << ((double)clk)/CLOCKS_PER_SEC << endl;

    return 0;
}

#include <bits/stdc++.h>

typedef long long ll;
typedef long long ull;

using namespace std;

const int mxN = 3e5+5;
const int mxK = 26;
const int mod = 998244353;

struct node
{
    int id;
    bool e;
    int mp[mxK];
    node(int _id)
    {
        id = _id;
        e = false;
        for(int i = 0; i < mxK; i++) mp[i] = -1;
    }
};
vector<node> trie;
void add(int x, int i, string& s)
{
    if(i == (int)s.size())
    {
        trie[x].e = true;
        return;
    }
    int key = s[i]-'a';
    if(trie[x].mp[key] == -1)
    {
        trie[x].mp[key] = trie.size();
        trie.push_back({(int)trie.size()});
    }
    add(trie[x].mp[key], i+1, s);
}

map<pair<int, int>, int> _index;
map<int, bool> vis;

bool exist(int u, int v)
{
    if(u < v) swap(u, v);
    return _index.find({u, v}) != _index.end();
}
int create(int u, int v)
{
    if(u < v) swap(u, v);
    int sz = _index.size();
    return _index[{u, v}] = sz;
}
int key(int u, int v)
{
    if(u < v) swap(u, v);
    if(exist(u, v))
    {
        return _index[{u, v}];
    }
    else
    {
        return create(u, v);
    }
}

struct matrix
{
    int k;
    vector<vector<ll>> a;
    matrix(int kk)
    {
        k = kk;
        a = vector<vector<ll>>(k);
        for(int i = 0; i < k; i++)
        {
            a[i] = vector<ll>(k, 0);
        }
    }

    void print()
    {
        for(int j = 0; j < k; j++)
        {
            for(int i = 0; i < k; i++)
            {
                cout << a[j][i] << " ";
            }
            cout << "\n";
        }
    }
};

matrix mul(matrix a, matrix b)
{
    int k = a.k;
    matrix ret(k);
    for(int i = 0; i < k; i++)
    {
        for(int j = 0; j < k; j++)
        {
            for(int q = 0; q < k; q++)
            {
                ret.a[i][q] = (ret.a[i][q] + a.a[i][j] * b.a[j][q]) % mod;
            }
        }
    }
    return ret;
}

matrix powb(matrix mat, ll x)
{
    int k = mat.k;
    matrix ret(k);
    for(int i = 0; i < k; i++) ret.a[i][i] = 1;
    while(x)
    {
        if(x&1)
        {
            ret = mul(mat, ret);
        }
        mat = mul(mat, mat);
        x >>= 1;
    }
    return ret;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    trie.push_back({0});
    int n; ll m; cin >> n >> m;
    for(int i = 0; i < n; i++)
    {
        string s; cin >> s;
        add(0, 0, s);
    }
    queue<pair<int, int>> q;
    q.push({0, 0}); /// nalazim se na 0 0
    create(0, 0);
    while(!q.empty())
    {
        auto pos = q.front(); q.pop();
        int u = pos.first, v = pos.second;
        ///probaj svaku tranziciju
        for(int k = 0; k < mxK; k++)
        {
            if(trie[u].mp[k] == -1 || trie[v].mp[k] == -1) continue;///nema
            int up = trie[u].mp[k], vp = trie[v].mp[k];
            if(!exist(up, vp))
            {
                create(up, vp);
                q.push({up, vp});
            }
            if(trie[up].e && !exist(0, vp))
            {
                create(0, vp);
                q.push({0, vp});
            }
            if(trie[vp].e && !exist(up, 0))
            {
                create(up, 0);
                q.push({up, 0});
            }
        }
    }
    int k = _index.size(); ///create matrix [k x k]
    matrix mat(k);
    q.push({0, 0});
    vis[key(0, 0)] = 1;
    while(!q.empty())
    {
        auto pos = q.front(); q.pop();
        int u = pos.first, v = pos.second;
        int x = key(u, v);
        ///probaj svaku tranziciju
        for(int k = 0; k < mxK; k++)
        {
            if(trie[u].mp[k] == -1 || trie[v].mp[k] == -1) continue;///nema
            int up = trie[u].mp[k], vp = trie[v].mp[k];
            mat.a[x][key(up, vp)]++;
            if(!vis[key(up, vp)])
            {
                vis[key(up, vp)] = 1;
                q.push({up, vp});
            }
            if(trie[up].e)
            {
                mat.a[x][key(0, vp)]++;
                if(!vis[key(0, vp)])
                {
                    vis[key(0, vp)] = 1;
                    q.push({0, vp});
                }
            }
            if(trie[vp].e)
            {
                mat.a[x][key(up, 0)]++;
                if(!vis[key(up, 0)])
                {
                    vis[key(up, 0)] = 1;
                    q.push({up, 0});
                }
            }
            if(trie[up].e && trie[vp].e)
            {
                mat.a[x][0]++;
            }
        }
    }
    mat = powb(mat, m);
    cout << mat.a[0][0];
}

/*
8 10000000
abcde
bcdef
cdefg
defga
efgab
fgabc
gabcd
a
*/

#include <bits/stdc++.h>

#define F first
#define S second

using namespace std;
using ll = long long;
using pi = pair<int, int>;
using vi = vector<int>;
using vpi = vector<pi>;

template<class T> bool ckmin(T& a, T b) { return b < a ? a = b, true : false; }
template<class T> bool ckmax(T& a, T b) { return a < b ? a = b, true : false; }

const int MOD = 998244353;

struct Matrix {
    int n;
    vector<vector<int>> w;

    Matrix(const int n) : n(n), w(n, vector<int>(n)) { }

    Matrix operator * (const Matrix& m) const {
        Matrix res(n);

        for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j) {
            if (!w[i][j]) continue;
            for (int t = 0; t < n; ++t) {
                res.w[i][t] = (res.w[i][t] + (ll) w[i][j] * m.w[j][t]) % MOD;
            }
        }

        return res;
    }
};

void dfs_forw(int v, const int r, const vector<vector<int>>& w, vector<char>& used) {
    if (used[v]) return;
    used[v] = true;

    for (int i = 0; i < r; ++i) {
        if (w[v][i]) dfs_forw(i, r, w, used);
    }
}

void dfs_back(int v, const int r, const vector<vector<int>>& w, vector<char>& used) {
    if (used[v]) return;
    used[v] = true;

    for (int i = 0; i < r; ++i) {
        if (w[i][v]) dfs_back(i, r, w, used);
    }
}

void solve() {
    int n, m; cin >> n >> m;

    map<string, int> id;
    id[""] = 0;
    int vc = 1;

    vector<string> v(n), phi { "" };
    for (string& s : v) {
        cin >> s;
        for (int i = 1; i <= size(s); ++i) {
            auto t = s.substr(0, i);
            if (!id.count(t)) {
                id[t] = vc++;
                phi.push_back(t);
            }
        }
    }

    const int k = size(id);
    const int r = k * k;
    vector w(r, vector<int>(r));

    for (int ia = 0; ia < k; ++ia)
    for (int ib = 0; ib < k; ++ib) {
        for (char ch = 'a'; ch <= 'z'; ch++) {
            auto ta = phi[ia] + ch; const int sa = id.count(ta) ? id[ta] : -1;
            auto tb = phi[ib] + ch; const int sb = id.count(tb) ? id[tb] : -1;

            for (int ja = 0; ja < n; ++ja) {
                if (ta != v[ja]) continue;
                for (int jb = 0; jb < n; ++jb) {
                    if (tb != v[jb]) continue;
                    w[ia*k+ib][0]++;
                }

                if (sb != -1) w[ia*k+ib][sb]++;
            }

            for (int jb = 0; jb < n; ++jb) {
                if (sa != -1 && tb == v[jb]) w[ia*k+ib][sa*k]++;
            }

            if (sa != -1 && sb != -1) w[ia*k+ib][sa*k+sb]++;
        }
    }

    vector<char> u1(r), u2(r);
    int us = 0;

    dfs_forw(0, r, w, u1);
    dfs_back(0, r, w, u2);

    vector<int> tid;

    for (int i = 0; i < r; ++i) {
        if (u1[i] && u2[i]) {
            tid.push_back(i);
        }
    }

    const int p = size(tid);

    Matrix ans(p), mul(p);

    for (int i = 0; i < p; ++i)
    for (int j = 0; j < p; ++j) {
        mul.w[i][j] = w[tid[i]][tid[j]];
    }

    for (int i = 0; i < p; ++i) ans.w[i][i] = 1;

    for (; m != 0; m >>= 1) {
        if (m & 1) ans = ans * mul;
        mul = mul * mul;
    }

    cout << ans.w[0][0] << '\n';
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    int t = 1;
    // cin >> t;
    while (t--) solve();
}

// dp[0] = 1
// dp[1] = 1
// dp[2] = 2
// dp[3] = 3
// dp[4] = 5

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=250,p=998244353;
int n,m,k,d[N][N],s[N][26];
bool pd[N];
char ch;
struct mtx{
	int a[N][N];
	inline mtx operator *(const mtx &v)const{
		mtx w;memset(w.a,0,sizeof w.a);
		for(int i=0;i<k;i++) for(int j=0;j<k;j++) if(a[i][j])
			for(int l=0;l<k;l++) w.a[i][l]=(w.a[i][l]+(ll)a[i][j]*v.a[j][l])%p;
		return w;
	}
}x,y;
int dfs(int u,int v){
	if(u>v) swap(u,v);
	if(d[u][v]>=0) return d[u][v];
	int o=d[u][v]=k++;
	for(int i=0,_u,_v;i<26;i++){
		_u=s[u][i];_v=s[v][i];
		if(!_u||!_v) continue;
		x.a[o][dfs(_u,_v)]++;
		if(pd[_u]) x.a[o][dfs(0,_v)]++;
		if(pd[_v]) x.a[o][dfs(_u,0)]++;
		if(pd[_u]&&pd[_v]) x.a[o][0]++;
	}
	return o;
}
int main(){
	cin>>n>>m;memset(d,-1,sizeof d);
	for(int i=1,u=0,v;i<=n;i++){
		scanf("\n");ch=getchar();
		while(ch>='a'&&ch<='z'){
			v=ch-'a';
			if(!s[u][v]) s[u][v]=++k;
			u=s[u][v];ch=getchar();
		}
		pd[u]=1;u=0;
	}
	k=0;dfs(0,0);y=x;m--;
	while(m){
		if(m&1) y=y*x;
		m>>=1;x=x*x;
	}
	cout<<y.a[0][0];
}

#include<bits/stdc++.h>
using namespace std;
const int N=2200,mod=998244353;
int n,m,ans;

int ch_[N][26],ch[N][26],nxt[N],id=1;
char T[N];
char S[N];
bool tag[N];

int vis[N][N],ct;

queue <int> q;
void getnxt(){
	q.push(1);
	while(!q.empty()){
		int x=q.front();
		q.pop();
		for(int i=0;i<26;i++){
			if(ch_[x][i]){
				int v=ch_[x][i];
				q.push(v);
				nxt[v]=ch_[nxt[x]][i];
			}
			else ch_[x][i]=ch_[nxt[x]][i];
		}
	}
}

struct mat{
	int M[220][220];
	mat(int x=0){
		for(int i=1;i<=ct;i++)
			for(int j=1;j<=ct;j++)
				M[i][j]=(i==j)*x;
	}
};
mat operator +(mat X,mat Y){
	mat T;
	for(int i=1;i<=ct;i++)
		for(int j=1;j<=ct;j++)
			T.M[i][j]=(X.M[i][j]+Y.M[i][j])%mod;
	return T;
}
mat operator *(mat X,mat Y){
	mat T;
	for(int k=1;k<=ct;k++)
		for(int i=1;i<=ct;i++)
			for(int j=1;j<=ct;j++)
				T.M[i][j]=(T.M[i][j]+1ll*X.M[i][k]*Y.M[k][j]%mod)%mod;
	return T;
}

mat ksm(mat A,int x){
	mat T(1);
	while(x){
		if(x & 1) T=T*A;
		A=A*A;
		x>>=1;
	}
	return T;
}

mat A(0),P(0);
void fil(int xx,int yy,int x,int y){
	if(xx>yy) swap(xx,yy);
	if(x>y) swap(x,y);
	if(!vis[x][y] || !vis[xx][yy]) return ;
	A.M[vis[xx][yy]][vis[x][y]]++;
}

int main(){
	cin>>n>>m;
	for(int i=0;i<26;i++) ch_[0][i]=1;
	for(int i=1;i<=n;i++){
		scanf("\n%s",S+1);
		int len=strlen(S+1);
		int x=1;
		for(int t=1;t<=len;t++){
			char c=S[t]-'a';
			if(!ch[x][c]) ch_[x][c]=ch[x][c]=++id,T[id]=T[x]+c;
			x=ch[x][c];
		}
		tag[x]=1;
	}
	getnxt();
	for(int u=1;u<=id;u++){
		int x=u;
		while(x){
			int p=min(x,u),q=max(x,u);
			if(!vis[p][q]) vis[p][q]=++ct;
			x=nxt[x];
		}
	}
	P.M[1][1]=1;
	for(int i=1;i<=id;i++){
		for(int j=1;j<=id;j++){
			if(!vis[i][j]) continue;
			for(int c=0;c<26;c++){
				int ni=ch[i][c],nj=ch[j][c];
				if(ni && nj) fil(ni,nj,i,j);
				if(ni && tag[nj]) fil(ni,1,i,j);
				if(nj && tag[ni]) fil(1,nj,i,j);
				if(tag[ni] && tag[nj]) fil(1,1,i,j);
			}
		}
	}
	cout<<(ksm(A,m)*P).M[1][1];
}

#include <bits/stdc++.h>

using namespace std;

const int MOD = 998244353;
const int K = 161;

struct node{
	int nxt[26];
	bool term;
	node(){
		memset(nxt, -1, sizeof(nxt));
		term = false;
	};
	int& operator [](const int x){
		return nxt[x];
	}
};

vector<node> trie;

int tot;

void add(const string &s){
	int cur = 0;
	int d = 1;
	for (const char &c : s){
		++d;
		if (trie[cur][c - 'a'] == -1){
			trie[cur][c - 'a'] = trie.size();
			trie.push_back(node());
			tot += d;
		}
		cur = trie[cur][c - 'a'];
	}
	trie[cur].term = true;
}

int add(int a, int b){
	a += b;
	if (a >= MOD)
		a -= MOD;
	return a;
}

int mul(int a, int b){
	return a * 1ll * b % MOD;
}

typedef array<array<int, K>, K> mat;

mat operator *(const mat &a, const mat &b){
	mat c;
	for(int i = 0; i < K; i++) for(int j = 0; j < K; j++) c[i][j] = 0;
	for(int i = 0; i < K; i++) for(int j = 0; j < K; j++)
		for(int k = 0; k < K; k++)
			c[i][j] = add(c[i][j], mul(a[i][k], b[k][j]));
	return c;
}

mat binpow(mat a, long long b){
	mat res;
	for(int i = 0; i < K; i++) for (int j = 0; j < K; j++) res[i][j] = i == j;
	while (b){
		if (b & 1)
			res = res * a;
		a = a * a;
		b >>= 1;
	}
	return res;
}

map<pair<int, int>, int> num;
queue<pair<int, int>> q;

int get(int v, int u){
	if (v > u) swap(v, u);
	if (!num.count({v, u})){
		int k = num.size();
		assert(k < K);
		num[{v, u}] = k;
		q.push({v, u});
	}
	return num[{v, u}];
}

int main() {
	int n;
	long long m;
	cin >> n >> m;
	trie = vector<node>(1, node());
	tot = 1;
	for(int i = 0; i < n; i++){
		string s;
		cin >> s;
		add(s);
	}
	q.push({0, 0});
	num[q.front()] = 0;
	mat init;
	for(int i = 0; i < K; i++) for(int j = 0; j < K; j++) init[i][j] = 0;
	while (!q.empty()){
		int v = q.front().first;
		int u = q.front().second;
		q.pop();
		int x = get(v, u);
		for(int c = 0; c < 26; c++){
			int tov = trie[v][c];
			int tou = trie[u][c];
			if (tov == -1 || tou == -1) continue;
			++init[x][get(tov, tou)];
			if (trie[tov].term) ++init[x][get(0, tou)];
			if (trie[tou].term) ++init[x][get(tov, 0)];
			if (trie[tov].term && trie[tou].term) ++init[x][0];
		}
	}
	init = binpow(init, m);
	printf("%d\n", init[0][0]);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
#define DEBUG(...) debug(#__VA_ARGS__, __VA_ARGS__)
#else
#define DEBUG(...) 6
#endif

template<typename T, typename S> ostream& operator << (ostream &os, const pair<T, S> &p) {return os << "(" << p.first << ", " << p.second << ")";}
template<typename C, typename T = decay<decltype(*begin(declval<C>()))>, typename enable_if<!is_same<C, string>::value>::type* = nullptr>
ostream& operator << (ostream &os, const C &c) {bool f = true; os << "["; for (const auto &x : c) {if (!f) os << ", "; f = false; os << x;} return os << "]";}
template<typename T> void debug(string s, T x) {cerr << "\033[1;35m" << s << "\033[0;32m = \033[33m" << x << "\033[0m\n";}
template<typename T, typename... Args> void debug(string s, T x, Args... args) {for (int i=0, b=0; i<(int)s.size(); i++) if (s[i] == '(' || s[i] == '{') b++; else
if (s[i] == ')' || s[i] == '}') b--; else if (s[i] == ',' && b == 0) {cerr << "\033[1;35m" << s.substr(0, i) << "\033[0;32m = \033[33m" << x << "\033[31m | "; debug(s.substr(s.find_first_not_of(' ', i + 1)), args...); break;}}

template<int MOD>
struct ModInt {
    long long v;
    ModInt(long long _v = 0) {v = (-MOD < _v && _v < MOD) ? _v : _v % MOD; if (v < 0) v += MOD;}
    ModInt& operator += (const ModInt &other) {v += other.v; if (v >= MOD) v -= MOD; return *this;}
    ModInt& operator -= (const ModInt &other) {v -= other.v; if (v < 0) v += MOD; return *this;}
    ModInt& operator *= (const ModInt &other) {v = v * other.v % MOD; return *this;}
    ModInt& operator /= (const ModInt &other) {return *this *= inverse(other);}
    bool operator == (const ModInt &other) const {return v == other.v;}
    bool operator != (const ModInt &other) const {return v != other.v;}
    friend ModInt operator + (ModInt a, const ModInt &b) {return a += b;}
    friend ModInt operator - (ModInt a, const ModInt &b) {return a -= b;}
    friend ModInt operator * (ModInt a, const ModInt &b) {return a *= b;}
    friend ModInt operator / (ModInt a, const ModInt &b) {return a /= b;}
    friend ModInt operator - (const ModInt &a) {return 0 - a;}
    friend ModInt power(ModInt a, long long b) {ModInt ret(1); while (b > 0) {if (b & 1) ret *= a; a *= a; b >>= 1;} return ret;}
    friend ModInt inverse(ModInt a) {return power(a, MOD - 2);}
    friend istream& operator >> (istream &is, ModInt &m) {is >> m.v; m.v = (-MOD < m.v && m.v < MOD) ? m.v : m.v % MOD; if (m.v < 0) m.v += MOD; return is;}
    friend ostream& operator << (ostream &os, const ModInt &m) {return os << m.v;}
};
using M = ModInt<998244353>;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template<typename T>
vector<T> berlekampMassey(const vector<T> &s) {
    vector<T> c;    // the linear recurrence sequence we are building
    vector<T> oldC; // the best previous version of c to use (the one with the rightmost left endpoint)
    int f = -1;     // the index at which the best previous version of c failed on
    for (int i=0; i<(int)s.size(); i++) {
        // evaluate c(i)
        // delta = s_i - \sum_{j=1}^n c_j s_{i-j}
        // if delta == 0, c(i) is correct
        T delta = s[i];
        for (int j=1; j<=(int)c.size(); j++)
            delta -= c[j-1] * s[i-j];   // c_j is one-indexed, so we actually need index j - 1 in the code
        if (delta == 0)
            continue;   // c(i) is correct, keep going
        // now at this point, delta != 0, so we need to adjust it
        if (f == -1) {
            // this is the first time we're updating c
            // s_i was the first non-zero element we encountered
            // we make c of length i + 1 so that s_i is part of the base case
            c.resize(i + 1);
            for (T &x : c)
                x = rng();  // just to prove that the initial values don't matter in the first step, I will set to random values
            f = i;
        } else {
            // we need to use a previous version of c to improve on this one
            // apply the 5 steps to build d
            // 1. set d equal to our chosen sequence
            vector<T> d = oldC;
            // 2. multiply the sequence by -1
            for (T &x : d)
                x = -x;
            // 3. insert a 1 at the front
            d.insert(d.begin(), 1);
            // 4. multiply the sequence by delta / d(f + 1)
            T df1 = 0;  // d(f + 1)
            for (int j=1; j<=(int)d.size(); j++)
                df1 += d[j-1] * s[f+1-j];
            assert(df1 != 0);
            for (T &x : d)
                x *= delta / df1;
            // 5. insert i - f - 1 zeros in front
            vector<T> zeros(i - f - 1);
            zeros.insert(zeros.end(), d.begin(), d.end());
            d = zeros;
            // now we have our new recurrence: c + d
            vector<T> temp = c; // save the last version of c because it might have a better left endpoint
            c.resize(max(c.size(), d.size()));
            for (int j=0; j<(int)d.size(); j++)
                c[j] += d[j];
            // finally, let's consider updating oldC
            if (i - (int) temp.size() > f - (int) oldC.size()) {
                // better left endpoint, let's update!
                oldC = temp;
                f = i;
            }
        }
    }
    return c;
}

template<typename T>
T solve(const vector<T> &c, const vector<T> &s, long long k) {
    int n = (int) c.size();
    assert(c.size() <= s.size());

    auto mul = [&] (const vector<T> &a, const vector<T> &b) -> vector<T> {
        vector<T> ret(a.size() + b.size() - 1);
        for (int i=0; i<(int)a.size(); i++)
            for (int j=0; j<(int)b.size(); j++)
                ret[i+j] += a[i] * b[j];
        for (int i=(int)ret.size()-1; i>=n; i--)
            for (int j=n-1; j>=0; j--)
                ret[i-j-1] += ret[i] * c[j];
        ret.resize(min((int) ret.size(), n));
        return ret;
    };

    vector<T> a = n == 1 ? vector<T>{c[0]} : vector<T>{0, 1}, x{1};
    for (; k>0; k/=2) {
        if (k % 2)
            x = mul(x, a);
        a = mul(a, a);
    }
    x.resize(n);

    T ret = 0;
    for (int i=0; i<n; i++)
        ret += x[i] * s[i];
    return ret;
}

M dp[8][5][8][5], ndp[8][5][8][5];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n, m;
    cin >> n >> m;
    vector<string> s(n);
    vector<vector<int>> nxt(26);
    for (int i=0; i<n; i++) {
        cin >> s[i];
        nxt[s[i][0]-'a'].push_back(i);
    }

    dp[0][0][0][0] = 1;
    vector<M> seq{1};
    for (int i=0; i<min(m, 2000); i++) {
        for (int a=0; a<n; a++)
            for (int la=0; la<(int)s[a].size(); la++)
                for (int b=0; b<n; b++)
                    for (int lb=0; lb<(int)s[b].size(); lb++)
                        ndp[a][la][b][lb] = 0;
        for (int a=0; a<n; a++)
            for (int la=0; la<(int)s[a].size(); la++)
                for (int b=0; b<n; b++)
                    for (int lb=0; lb<(int)s[b].size(); lb++)
                        for (char c='a'; c<='z'; c++) {
                            if ((la != 0 && s[a][la] != c) || (lb != 0 && s[b][lb] != c))
                                continue;
                            if (la == 0) {
                                if (lb == 0) {
                                    for (int j : nxt[c-'a'])
                                        for (int k : nxt[c-'a'])
                                            ndp[j][s[j].size() > 1][k][s[k].size() > 1] += dp[a][la][b][lb];
                                } else {
                                    for (int j : nxt[c-'a'])
                                        ndp[j][s[j].size() > 1][b][lb + 1 == (int) s[b].size() ? 0 : lb + 1] += dp[a][la][b][lb];
                                }
                            } else if (lb == 0) {
                                for (int k : nxt[c-'a'])
                                    ndp[a][la + 1 == (int) s[a].size() ? 0 : la + 1][k][s[k].size() > 1] += dp[a][la][b][lb];
                            } else {
                                ndp[a][la + 1 == (int) s[a].size() ? 0 : la + 1][b][lb + 1 == (int) s[b].size() ? 0 : lb + 1] += dp[a][la][b][lb];
                            }
                        }
        memcpy(dp, ndp, sizeof(ndp));
        M cur = 0;
        for (int a=0; a<n; a++)
            for (int b=0; b<n; b++)
                cur += dp[a][0][b][0];
        seq.push_back(cur);
    }

    if (m < (int) seq.size())
        cout << seq[m] << "\n";
    else
        cout << solve(berlekampMassey(seq), seq, m) << "\n";

    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define ti3 tuple<int,int,int>
const int inf = 1 << 30;
const ll linf = 1e18;
const ll mod = 998244353;
const db EPS = 1e-7;
template<class T> void chmin(T& x, T y){if(x > y) x = y;}
template<class T> void chmax(T& x, T y){if(x < y) x = y;}

template<long long mod>
struct modint{
    long long num;

    constexpr modint(long long x = 0) : num((x + mod) % mod) {}

    constexpr modint &operator += (const modint& rhs){
        num = (num + rhs.num) % mod;
        return *this;
    }
    constexpr modint &operator -= (const modint& rhs){
        num  -= rhs.num;
        while(num < 0) num += mod;
        num %= mod;
        return *this;
    }
    constexpr modint &operator *= (const modint& rhs){
        num = num * rhs.num % mod;
        return *this;
    }
    constexpr modint &operator /= (modint rhs){
        int exp = mod - 2;
        while(exp > 0){
            if(exp % 2){
                *this *= rhs;
            }
            rhs *= rhs;
            exp /= 2;
        }
        return *this;
    }

    constexpr modint operator ++ (){
        ++num;
        return *this;
    }
    constexpr modint operator ++ (int n){
        modint tmp = *this;
        ++(*this);
        return tmp;
    }
    constexpr modint operator -- (){
        --num;
        return *this;
    }
    constexpr modint operator -- (int n){
        const modint tmp = *this;
        --(*this);
        return tmp;
    }

    void modpow(ll y){
        modint tmp = (*this);
        (*this) = 1;
        while(y > 0){
            if(y % 2){
                (*this) *= tmp;
            }
            tmp *= tmp;
            y /= 2;
        }
    }

    constexpr modint operator + (const modint& rhs) const {
        return modint(*this) += rhs;
    }
    constexpr modint operator - (const modint& rhs) const {
        return modint(*this) -= rhs;
    }
    constexpr modint operator * (const modint& rhs) const {
        return modint(*this) *= rhs;
    }
    constexpr modint operator / (const modint& rhs) const {
        return modint(*this) /= rhs;
    }

    friend ostream &operator << (ostream& lhs, const modint& rhs){
        return lhs << rhs.num;
    }

    friend istream &operator >> (istream& lhs, modint& rhs){
        lhs >> rhs.num;
        return lhs;
    }
};

#define mint modint<mod>
#define mat vector<vector<mint>>

mint modpow(mint x, int y){
    if(y == 0) return 1;
    mint e = modpow(x, y / 2);
    e = e * e;
    return e * (y % 2 == 0 ? 1 : x);
}

mat matmul(mat a, mat b){
    int n1 = a.size(), m1 = a[0].size(), m2 = b[0].size();

    mat res;
    res.resize(n1, vector<mint>(m2, 0));
    for(int i = 0; i < n1; i++){
        for(int j = 0; j < m2; j++){
            for(int k = 0; k < m1; k++){
                res[i][j] += a[i][k] * b[k][j];
            }
        }
    }
    return res;
}

vector<mint> matvec(mat m, vector<mint> v) {
    vector<mint> res(m.size(), 0);
    for (int i = 0; i < m.size(); i++) {
        for (int j = 0; j < v.size(); j++) {
            res[i] += m[i][j] * v[j];
        }
    }
    return res;
}

mat matpow(mat m, ll y) {
    if (y == 0) {
        for (int i = 0; i < m.size(); i++) {
            for (int j = 0; j < m[i].size(); j++) {
                m[i][j] = (i == j ? 1 : 0);
            }
        }
        return m;
    }
    mat res = matpow(m, y / 2);
    res = matmul(res, res);
    if (y & 1) res = matmul(res, m);
    return res;
}

int n, m;
string word[10];
set<string> st;
vector<string> v = {""};
int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> word[i];
        for (int j = 1; j <= word[i].length(); j++) {
            string t = word[i].substr(0, j);
            if (st.find(t) == st.end()) {
                st.insert(t);
                v.push_back(t);
            }
        }
    }

    vector<pii> as = {{0, 0}};

    for (int i = 1; i < v.size(); i++) {
        for (int j = i; j < v.size(); j++) {
            string s = v[i], t = v[j];
            if (s.length() < t.length()) swap(s, t);
            if (s.substr(s.length() - t.length(), t.length()) == t) {
                as.push_back({i, j});
            }
        }
    }

    int sz = as.size();
    mat A = vector<vector<mint>>(sz, vector<mint>(sz, 0));
    vector<mint> vs(sz, 0);

    for (int i = 0; i < sz; i++) {
        vs[i] = v[as[i].first].length() == 1 && v[as[i].second].length() == 1;
    }

    for (int i = 1; i < sz; i++) {
        bool flag[2] = {};
        for (int j = 0; j < n; j++) {
            if (v[as[i].first] == word[j]) flag[0] = 1;
            if (v[as[i].second] == word[j]) flag[1] = 1;
        }
        A[0][i] = flag[0] & flag[1];

        for (int j = 1; j < sz; j++) {
            auto judge = [&](string s, string t) -> int {
                if (s.length() == t.length() + 1 && s.substr(0, t.length()) == t) return 1;
                if (s.length() != 1) return 0;
                for (int i = 0; i < n; i++) {
                    if (t == word[i]) return 1;
                }
                return 0;
            };

            A[i][j] += judge(v[as[i].first], v[as[j].first]) & judge(v[as[i].second], v[as[j].second]);
            if (as[i].first != as[i].second) {
                A[i][j] += judge(v[as[i].first], v[as[j].second]) & judge(v[as[i].second], v[as[j].first]);
            }

        }
    }
    vs = matvec(matpow(A, m), vs);
    cout << vs[0] << endl;
}

#include <bits/stdc++.h>

using namespace std;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(x) (x).begin (),(x).end()
#define sqrt(x) sqrt(abs(x))
#define re return
#define sz(x) ((int)(x).size ())
#define prev PREV
#define next NEXT

using ll = long long;
using ii = pair<int, int>;
using ld = long double;
using D = double;
using vi = vector<int>;
using vii = vector<ii>;
using vvi = vector<vi>;
using vs = vector<string>;

template<typename T> T abs (T x) { re x < 0 ? -x : x; }
template<typename T> T sgn (T x) { re x < 0 ? -1 : (x > 0 ? 1 : 0); }
template<typename T> T sqr (T x) { re x * x; }
template<typename T> T gcd (T a, T b) { re a ? gcd (b % a, a) : b; }

const int N = 1700;
const int mod = 998244353;

int n;
int m;
int r;
int g[N][N];
int was[60][60];
int num[60][60];
ii w[N];
string s[8];
int e[N][N];
int h[N][N];
map<string, int> cnt;
map<string, int> nump;
vs p;
int o;

int go (int i, int j) {
	if (i > j) {
		swap (i, j);
	}
	if (was[i][j]) re num[i][j];
	was[i][j] = 1;
	num[i][j] = r;
	int x = r;
	w[r] = mp (i, j);
	r++;
//	cout << "|" << p[i] << "| |" << p[j] << "|" << endl;
	for (int c = 0; c < 26; c++)
		for (int a = 0; a < 2; a++)
			for (int b = 0; b < 2; b++) {
				string s = p[i] + char (c + 'a');
				string t = p[j] + char (c + 'a');
				int mul = 1;
				if (a == 1) { mul *= cnt[s]; s = ""; }
				if (b == 1) { mul *= cnt[t]; t = ""; }
				if (nump.count (s) && nump.count (t) && mul) {
//					printf ("%d %d -> |%s| |%s|\n", i, j, s.c_str (), t.c_str ());
					int y = go (nump[s], nump[t]);
					g[x][y] += mul;
				}
			}
	re x;
}

int main () {
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		cin >> s[i];
		for (int j = 0; j <= sz (s[i]); j++) p.pb (s[i].substr (0, j));
		cnt[s[i]]++;
	}
	sort (all (p));
	p.resize (unique (all (p)) - p.begin ());
	o = sz (p);
	for (int i = 0; i < o; i++) nump[p[i]] = i;
	go (0, 0);
/*	for (int i = 0; i < r; i++) {
		printf ("%d %d: ", w[i].fi, w[i].se);
		for (int j = 0; j < r; j++) printf ("%d ", g[i][j]);
		printf ("\n");
	}*/
//	cerr << r << endl;
//	cerr << clock () << endl;
	for (int i = 0; i < r; i++)
		for (int j = 0; j < r; j++)
			e[i][j] = int (i == j);
	while (m) {
		if (m & 1) {
			for (int i = 0; i < r; i++)
				for (int j = 0; j < r; j++) {
					h[i][j] = 0;
					for (int k = 0; k < r; k++)
						h[i][j] = (h[i][j] + (ll)e[i][k] * g[k][j]) % mod;
				}
			for (int i = 0; i < r; i++)
				for (int j = 0; j < r; j++)
					e[i][j] = h[i][j];
		}
		m /= 2;
		for (int i = 0; i < r; i++)
			for (int j = 0; j < r; j++) {
				h[i][j] = 0;
				for (int k = 0; k < r; k++)
					h[i][j] = (h[i][j] + (ll)g[i][k] * g[k][j]) % mod;
			}
		for (int i = 0; i < r; i++)
			for (int j = 0; j < r; j++)
				g[i][j] = h[i][j];
	}
	printf ("%d\n", e[0][0]);
	re 0;
}

#include<bits/stdc++.h>
using namespace std;
#define MAXN 300005
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=0x7f7f7f7f7f7f;
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int qkpow(int a,int s){int t=1;while(s){if(s&1)t=1ll*a*t%mo;a=1ll*a*a%mo;s>>=1;}return t;}
int n,m,idx,len[10],sum,id[10][10];
struct matrix{
	int c[185][185];
	matrix(){memset(c,0,sizeof(c));}
	matrix operator * (const matrix &rhs){
		matrix res;
		for(int i=1;i<=idx;i++)
			for(int k=1;k<=idx;k++)
				if(c[i][k])for(int j=1;j<=idx;j++)
					res.c[i][j]=add(res.c[i][j],1ll*c[i][k]*rhs.c[k][j]%mo);
		return res;
	}
	void print(){
		for(int i=1;i<=idx;i++,puts(""))
			for(int j=1;j<=idx;j++)
				printf("%d ",c[i][j]);
	}
}A,P[35],T;
char str[10][10];
signed main(){
	read(n);read(m);
	for(int i=1;i<=n;i++){
		scanf("%s",str[i]+1);len[i]=(int)strlen(str[i]+1);
		for(int j=2;j<=len[i];j++)id[i][j]=++idx;
	}
	idx++;int nod=idx;//printf("%d\n",nod);
	for(int i=1;i<=n;i++)id[i][1]=nod;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=len[i];j++)
			for(int k=1;k<=n;k++){
				bool fg=0;int lim=min(len[i]-j+1,len[k]);
				for(int l=1;l<=lim;l++)
					if(str[i][j+l-1]!=str[k][l])fg=1;
				if(fg)continue;int las=id[i][j],now;
				for(int l=2;l<=lim;l++){now=++idx;A.c[las][now]++;las=now;}
				if(len[i]-j+1==len[k])A.c[las][nod]++;
				if(len[i]-j+1<len[k])A.c[las][id[k][lim+1]]++;
				if(len[i]-j+1>len[k])A.c[las][id[i][j+lim]]++;
			}
	P[0]=A;for(int i=1;i<30;i++)P[i]=P[i-1]*P[i-1];
	for(int i=1;i<=idx;i++)T.c[i][i]=1;
	for(int i=0;i<30;i++)if(m&(1<<i))T=T*P[i];
	printf("%d\n",T.c[nod][nod]);
	return 0;
}
/*
*/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
#include<cassert>
#include<set>
#include<complex>
#include<numeric>
#include<functional>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,LL> LP;
const int INF=1<<30;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}

template<typename T>T ext_gcd(T a,T b,T& x,T& y){
    //ax+by=gcd(a,b)
    if(a<b)return ext_gcd(b,a,y,x);
    if(b==0){
        x=1,y=0;
        return a;
    }
    T gcd_val=ext_gcd(b,a%b,x,y);
    swap(x,y);
    y-=x*(a/b);
    if(x>b)y+=(x/b)*a,x%=b;
    if(y>a)x+=(y/a)*b,y%=a;
    return gcd_val;
}

template<long long int mod,bool prime=false>class modint{
private:
    typedef long long int ll;
    ll val;

    ll gcd(ll a,ll b){
        if(a<b)swap(a,b);
        if(b==0)return a;
        return gcd(b,a%b);
    }
public:
    modint():val(0){}
    template<class T>modint(T a){
        val=(ll)a%mod;
        if(val<0)val+=mod;
    }

    ll value()const{return val;}
    ll get_mod()const{return mod;}

    modint& operator++(){
        val++;
        if(val==mod)val=0;
        return *this;
    }
    modint operator++(int){
        modint ans=*this;
        ++*this;
        return ans;
    }
    modint& operator--(){
        if(val==0)val=mod;
        val--;
        return *this;
    }
    modint operator--(int){
        modint ans=*this;
        --*this;
        return ans;
    }

    modint& operator+=(const modint& a){
        val+=a.value();
        if(val>=mod)val-=mod;
        return *this;
    }
    modint& operator-=(const modint& a){
        val-=a.value();
        if(val<0)val+=mod;
        return *this;
    }
    modint& operator*=(const modint& a){
        val*=a.value();
        if(val>=mod)val%=mod;
        return *this;
    }

    modint pow(ll index)const{
        assert(index>=0);
        if(prime && index>=mod-1)index%=mod-1;
        modint a=*this,ans=1;
        for(ll i=1;i>=0 && i<=index;i<<=1){
            if(index&i)ans*=a;
            a*=a;
        }
        return ans;
    }

    modint inverse()const{
        if(prime){
            assert(val!=0);
            return pow(mod-2);
        }
        ll x,y;
        ll g=ext_gcd<ll>(val,mod,x,y);
        assert(g==1);
        return x;
    }

    modint& operator/=(const modint& a){
        if(prime){
            *this=(*this)*a.inverse();
            return *this;
        }
        ll g=gcd(val,a.value());
        modint a2=a.value()/g;
        val/=g;
        *this=(*this)*a2.inverse();
        return *this;
    }

    friend modint operator-(const modint& a,const modint& b){return (modint)a-=b;}
    friend modint operator+(const modint& a,const modint& b){return (modint)a+=b;}
    friend modint operator*(const modint& a,const modint& b){return (modint)a*=b;}
    friend modint operator/(const modint& a,const modint& b){return (modint)a/=b;}
    friend bool operator==(const modint& a,const modint& b){return a.value()==b.value();}
    friend bool operator!=(const modint& a,const modint& b){return a.value()!=b.value();}

    friend modint pow(const modint& a,const ll b){return a.pow(b);}

    modint operator+() const{return *this;}
    modint operator-() const{return modint()-*this;}

    friend ostream& operator<<(ostream& os,const modint& a){
        os<<a.value();
        return os;
    }
    friend istream& operator>>(istream& is,modint& a){
        ll val;
        is>>val;
        a=val;
        return is;
    }
};

using modint107=modint<1'000'000'007,true>;
using modint109=modint<1'000'000'009,true>;
using mint=modint<998'244'353,true>;

template<typename type> class Matrix{
public:
    vector<vector<type>> vec_matrix;
private:
    void init(int n){
        vec_matrix.assign(n,vector<type>(n,0));
    }
public:
    Matrix(int n){
        init(n);
    }
    Matrix(vector<vector<type>> ma):vec_matrix(ma){};

    bool valid() const{
        int n=size();
        assert(n>0 && (int)vec_matrix[0].size()==n);
        if(n>0 && (int)vec_matrix[0].size()==n)return true;
        else return false;
    }

    void E(){
        valid();
        for(int i=0;i<size();i++){
            vec_matrix[i][i]=1;
        }
    }
    void E(int n){
        init(n);
        E();
    }

    int size() const{
        return vec_matrix.size();
    }

    Matrix& operator += (const Matrix& matrix_a){
        const vector<vector<type>>& vec_matrix_a=matrix_a.vec_matrix;
        valid(),matrix_a.valid();
        int i,j;
        int n=size();
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                vec_matrix[i][j]+=vec_matrix_a[i][j];
            }
        }
        return *this;
    }

    Matrix& operator *= (const Matrix& matrix_a){
        const vector<vector<type>>& vec_matrix_a=matrix_a.vec_matrix;
        valid(),matrix_a.valid();
        int i,j,k;
        int n=size();
        vector<vector<type>> vec_matrix_b(n,vector<type>(n,0));
        for(i=0;i<n;i++){
            for(k=0;k<n;k++){
                for(j=0;j<n;j++){
                    vec_matrix_b[i][j]+=vec_matrix[i][k]*vec_matrix_a[k][j];
                }
            }
        }
        vec_matrix=vec_matrix_b;
        return *this;
    }

    Matrix operator +(const Matrix& matrix_a){
        Matrix matrix_s=*this;
        matrix_s+=matrix_a;
        return matrix_s;
    }

    Matrix operator *(const Matrix& matrix_a){
        Matrix matrix_s=*this;
        matrix_s*=matrix_a;
        return matrix_s;
    }

    Matrix pow(Matrix& ma,long long int m){
        long long int p_b=1;
        Matrix<type> ms(ma.size());
        ms.E();
        for(;p_b<=m;p_b<<=1);
        for(p_b>>=1;p_b>0;p_b>>=1){
            ms*=ms;
            if(m&p_b)ms*=ma;
        }
        return ms;
    }
    Matrix& pow(long long int m){
        (*this)=pow((*this),m);
        return *this;
    }

    type get_matrix_element(int a,int b) const{
        assert(a<size() && b<size());
        return vec_matrix[a][b];
    }
};

namespace sol{

    void solve(){
        int n,m,p;
        int i,j,k;
        int a,b,c;
        cin>>n>>m;
        string sa,sb;
        vector<string> v1;
        set<string> s1,s2;
        map<pair<string,int>,int> m1;
        vector<pair<string,int>> vp;
        s1.insert("");
        for(i=0;i<n;i++){
            cin>>sa;
            v1.push_back(sa);
            s2.insert(sa);
            while(!sa.empty()){
                s1.insert(sa);
                sa.pop_back();
            }
        }
        for(auto& str:s1){
            sa=str;
            m1[{str,0}]=vp.size();
            vp.push_back({str,0});
            for(i=1;i<=str.size();i++){
                sa.erase(sa.begin());
                if(s1.find(sa)==s1.end())continue;
                m1[{str,i}]=vp.size();
                vp.push_back({str,i});
            }
        }
        p=vp.size();
        vector<vector<mint>> vm(p,vector<mint>(p));
        for(i=0;i<p;i++){
            sa=vp[i].first,a=vp[i].second;
            for(char ca='a';ca<='z';ca++){
                sa.push_back(ca);
                sb=sa.substr(a);
                if(s2.find(sa)!=s2.end() && s2.find(sb)!=s2.end())vm[i][m1[{"",0}]]++;
                if(s2.find(sa)!=s2.end() && s1.find(sb)!=s1.end())vm[i][m1[{sb,sb.size()}]]++;
                if(s2.find(sb)!=s2.end() && s1.find(sa)!=s1.end())vm[i][m1[{sa,sa.size()}]]++;
                if(m1.find({sa,a})!=m1.end())vm[i][m1[{sa,a}]]++;
                sa.pop_back();
            }
        }
        Matrix<mint> ma(vm);
        int id=m1[{"",0}];
        ma.pow(m);
        cout<<ma.get_matrix_element(id,id)<<endl;
    }
}

int main(){
    sol::solve();
}

#include <iostream>
#include <vector>
#include <chrono>
#include <random>
#include <cassert>
#include <map>

std::mt19937 rng((int) std::chrono::steady_clock::now().time_since_epoch().count());

const int ms = 200;
//const int ms = 5 * 8 * 5 * 8 + 4;
const int MOD = 998244353;

template <class T>
T fexp(T x, long long e) {
	T ans(1);
	for(; e > 0; e /= 2) {
		if(e & 1) ans = ans * x;
		x = x * x;
	}
	return ans;
}

template <int mod = MOD>
struct modBase {
	modBase(int v = 0) : val(v < 0 ? v + mod : v) {}
	int val;

	void operator += (modBase<mod> o) { *this = *this + o; }
	void operator -= (modBase<mod> o) { *this = *this - o; }
	void operator *= (modBase<mod> o) { *this = *this * o; }
	//void operator /= (modBase<mod> o) { *this = *this / o; }
	modBase<mod> operator * (modBase<mod> o) { return (int)((long long) val * o.val % mod); }
	//modBase<mod> operator / (modBase<mod> o) { return *this * fexp(o, mod - 2); }
	modBase<mod> operator + (modBase<mod> o) { return val + o.val >= mod ? val + o.val - mod : val + o.val; }
	modBase<mod> operator - (modBase<mod> o) { return val - o.val < 0 ? val - o.val + mod : val - o.val; }

	friend std::ostream& operator << (std::ostream &os, const modBase<mod> &p) {
		return os << p.val;
	}
	friend std::istream& operator >> (std::istream &is, modBase<mod> &p) {
		return is >> p.val;
	}
};

template<const int n, const int m, class T = modBase<>>
struct Matrix {
	T v[n][m];

	Matrix(int d = 0) {
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < m; j++) {
				v[i][j] = T(0);
			}
			if(i < m) {
				v[i][i] = T(d);
			}
		}
	}

	template<int mm>
	Matrix<n, mm, T> operator *(const Matrix<m, mm, T> &o) {
		Matrix<n, mm, T> ans;
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < mm; j++) {
				for(int k = 0; k < m; k++) {
					ans.v[i][j] = ans.v[i][j] + v[i][k] * o.v[k][j];
				}
			}
		}
		return ans;
	}
};

int c = 1;
int trie[ms][26];
int terminal[ms];

void add(const std::string &str) {
	int on = 0;
	for(auto ch : str) {
		//assert(c * c < ms);
		if(trie[on][ch - 'a'] == 0) trie[on][ch - 'a'] = c++;
		on = trie[on][ch - 'a'];
		//std::cout << on << '\n';
	}
	terminal[on]++;
}

int main() {
	//std::cout << "GOT HERE!" << std::endl;
	std::ios_base::sync_with_stdio(false); std::cin.tie(NULL);
	//std::cout << ms << '\n';
	int n, m;
	std::cin >> n >> m;
	while(n--) {
		std::string str;
		std::cin >> str;
		add(str);
	}
	std::map<int, int> mp;
	mp[0] = 0;
	std::vector<int> q(1, 0);
	auto getId = [&](int id) {
		int i = id / c, j = id % c;
		if(i > j) std::swap(i, j);
		id = i * c + j;
		if(!mp.count(id)) {
			int sz = (int) mp.size();
			mp[id] = sz;
			assert(sz < ms);
			q.push_back(id);
		}
		return mp[id];
	};
	Matrix<ms, ms> mat(0);
	for(int wtf = 0; wtf < (int) q.size(); wtf++) {
		int i = q[wtf] / c, j = q[wtf] % c;
		for(int ch = 0; ch < 26; ch++) if(trie[i][ch] && trie[j][ch]) {
			int u = trie[i][ch], v = trie[j][ch];
			mat.v[getId(u * c + v)][getId(i * c + j)] += 1;
			mat.v[getId(0)][getId(i * c + j)] += terminal[u] * terminal[v];
			if(terminal[v]) mat.v[getId(u * c)][getId(i * c + j)] += terminal[v];
			if(terminal[u]) mat.v[getId(v)][getId(i * c + j)] += terminal[u];
		}
	}
	std::cout << fexp(mat, m).v[0][0] << '\n';
}

// Exported by Exporter.exe

// Included from test.cpp
// cf 1511 F
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define F first
#define S second
#define MP make_pair
#define MTP make_tuple
#define R Read
#define RD Read_Digit
#define RP Read_P
#define RL Read_Loop
#define RLD Read_Loop_Digit
#define RLP Read_Loop_P
#ifdef ONLINE_JUDGE
	#define Debug(x) ;
	#define Debugln(x) ;
	#define Debug_Array(n,x) ;
	#define Debugln_Array(n,x) ;
	#define NL ;
#else
	#define Debug(x) printf("%s :", (#x)); _Debug(x)
	#define Debugln(x) printf("%s :", (#x)); _Debugln(x)
	#define Debug_Array(n,x) printf("%s :", (#x)); _Debug_Array((n), (x))
	#define Debugln_Array(n,x) printf("%s :", (#x)); _Debugln_Array((n), (x))
	#define NL printf("\n")
#endif
typedef long long int ll;
typedef unsigned long long int ull;

constexpr int kN = 170;
constexpr int kMod = 998244353;
// constexpr int kMod = int(1E9 + 7);
// constexpr int kInf = 0x3f3f3f3f;
// constexpr ll kInf = 0x3f3f3f3f3f3f3f3f;
// constexpr double kPi = acos(-1);
// constexpr double kEps = 1E-9;

// Included from C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp
// --- Get ---
static inline char Get_Raw_Char() {
	static char buf[1 << 16], *p = buf, *end = buf;
	if (p == end) {
		if ((end = buf + fread(buf, 1, 1 << 16, stdin)) == buf) return '\0';
		p = buf;
	}
	return *p++;
}

// --- Read ---
template <typename T> static inline void Read_P(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	return ;
}

template <typename T> static inline void Read(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	if (neg) n = -n;
	return ;
}

template <typename T> static inline void Read_Digit(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	return ;
}

// --- Read multiple ---
template <typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read(n); return Read(Fargs...);}
template <typename T, typename... Targs> static inline void Read_Digit(T &n, Targs&... Fargs) {Read_Digit(n); return Read_Digit(Fargs...);}
template <typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P(n); return Read_P(Fargs...);}

// --- Read Loop ---
template <typename T> static inline void Read_Loop_i(int i, T *a) {return Read(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_i(int i, T *a, Targs*... Fargs) {Read(a[i]); return Read_Loop_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_Digit_i(int i, T *a) {return Read_Digit(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_Digit_i(int i, T *a, Targs*... Fargs) {Read_Digit(a[i]); return Read_Loop_Digit_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_Digit(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_Digit_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_P_i(int i, T *a) {return Read_P(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_P_i(int i, T *a, Targs*... Fargs) {Read_P(a[i]); return Read_Loop_P_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_P(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_P_i(i, Fargs...);}

// --- Float ---
template <int mul, typename T> static inline void Read(T &n) {
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;

	if (neg) n = -n;
	return ;
}

template <int mul, typename T> static inline void Read_P(T &n) {
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;

	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;
	return ;
}

template <int mul, typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read<mul>(n); return Read<mul>(Fargs...);}
template <int mul, typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P<mul>(n); return Read_P<mul>(Fargs...);}

// --- init ---
inline void IOS() {ios::sync_with_stdio(false); cin.tie(0);}
inline void Freopen(const char *in, const char *out) {freopen(in, "r", stdin); freopen(out, "w", stdout);}

// --- Output ---
template <typename T> void Print(T x) {
	if (x < 0) {
		printf("-");
		x = -x;
	}
	if (x == 0) printf("0");
	else {
		static int val[100];
		int idx = -1;
		while (x) {
			val[++idx] = x % 10;
			x /= 10;
		}
		while (idx >= 0) printf("%d", val[idx--]);
	}
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp
template <typename T> inline void sort(vector<T> &v) {return sort(v.begin(), v.end());}
template <typename T> inline void sort_r(vector<T> &v) {return sort(v.begin(), v.end(), greater<T>());}

template <typename T> inline void reverse(vector<T> &v) {return reverse(v.begin(), v.end());}

template <typename T> inline void Merge(vector<T> &a, vector<T> &b, vector<T> &c) {
	if (c.size() < a.size() + b.size()) c.resize(a.size() + b.size());
	merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
	return ;
}

template <typename T> inline void Discrete(vector<T> &v) {sort(v); v.resize(unique(v.begin(), v.end()) - v.begin());}

template <typename T> using PQ = priority_queue<T>;
template <typename T> using PQ_R = priority_queue<T, vector<T>, greater<T>>;

template <typename T> inline T ABS(T n) {return n >= 0 ? n : -n;}
template <typename T> inline T gcd(T a, T b) {return b ? gcd(b, a % b) : a;}
template <typename T> inline T lcm(T a, T b) {return a * b / gcd(a, b);}
template <typename T, typename... Targs> inline T min(T a, T b, T c, Targs... args) {return min(a, min(b, c, args...));}
template <typename T, typename... Targs> inline T max(T a, T b, T c, Targs... args) {return max(a, max(b, c, args...));}
template <typename T, typename... Targs> inline void chmin(T &a, T b, Targs... args) {a = min(a, b, args...); return ;}
template <typename T, typename... Targs> inline void chmax(T &a, T b, Targs... args) {a = max(a, b, args...); return ;}

template <typename T> inline int Digit_Sum(T a) {
	int ans = 0;
	while (a) {
		ans += a % 10;
		a /= 10;
	}
	return ans;
}
template <typename T> inline int Num_Length(T a) {
	int ans = 1;
	while (a /= 10) ans++;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp
void _print(int x) {printf("%d", x);}
void _print(long long int x) {printf("%lld", x);}
void _print(double x) {printf("%lf", x);}
template <typename T> void _print(T x) {return x.out();}
template <typename T1, typename T2> void _print(pair<T1, T2> x) {printf("("); _print(x.first); printf(", "); _print(x.second); printf(")");}

template <typename T> void _Debug(T x) {_print(x); printf("\n");}
template <typename T> void _Debug(vector<T> v) {
	if (v.empty()) printf(" empty");
	else for (T i : v) printf(" "), _print(i);
	printf("\n");
}

template <typename T1, typename T2, typename T3> void _Debug(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf(" ");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf(" ");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf(" ");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf(" ");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(vector<T> v) {
	if (v.empty()) printf(" empty\n");
	else {
		for (T i : v) printf("\n"), _print(i);
		printf("\n");
	}
}

template <typename T1, typename T2, typename T3> void _Debugln(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf("\n");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf("\n");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf("\n");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf("\n");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debug_Array(int n, const T *x) {for (int i = 1; i <= n; i++) printf(" "), _print(x[i]); printf("\n");}
template <typename T> void _Debugln_Array(int n, const T *x) {printf("\n"); for (int i = 1; i <= n; i++) _print(x[i]), printf("\n");}
// End of C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp
// !!! Mod_Int<kMod> a = 1 or Mod_Int<kMod> a(1) checks if the value is valid (and is slow)
// !!! However, the following usage doesn't check if the value is valid
// !!! Mod_Int<kMod> a;
// !!! a = 1;
template <typename T1, typename T2> T1 Pow(T1 a, T2 b) {
	T1 ans(1);
	while (b) {
		if (b & 1) ans *= a;
		a *= a;
		b >>= 1;
	}
	return ans;
}

template <int kMod> struct Mod_Int {
	static constexpr int Mod() {return kMod;}

	int val;
	Mod_Int() : val(0) {}
	template <typename T> Mod_Int(const T &x) {
		if (x >= kMod) val = x % kMod;
		else if (x <= -kMod) {
			val = x % kMod;
			if (val < 0) val += kMod;
		}
		else if (x < 0) val = x + kMod;
		else val = x;
	}

	Mod_Int operator = (const Mod_Int &x) {
		val = x.val;
		return *this;
	}

	template <typename T> Mod_Int operator = (const T &x) {
		val = x;
		return *this;
	}

	Mod_Int inv() const {return Pow(*this, kMod - 2);}

	Mod_Int operator + (const Mod_Int &x) const {
		Mod_Int ans(val + x.val);
		if (ans.val >= kMod) ans.val -= kMod;
		return ans;
	}
	Mod_Int operator - (const Mod_Int &x) const {
		Mod_Int ans(val - x.val);
		if (ans.val < 0) ans.val += kMod;
		return ans;
	}
	Mod_Int operator * (const Mod_Int &x) const {return Mod_Int(1LL * val * x.val % kMod);}
	Mod_Int operator / (const Mod_Int &x) const {return *this * x.inv();}
	Mod_Int operator ^ (const Mod_Int &x) const {return Pow(*this, x.val);}
	Mod_Int operator << (const int &x) const {return ((1LL * val) << x) % kMod;}

	Mod_Int operator += (const Mod_Int &x) {return *this = *this + x;}
	Mod_Int operator -= (const Mod_Int &x) {return *this = *this - x;}
	Mod_Int operator *= (const Mod_Int &x) {return *this = *this * x;}
	Mod_Int operator /= (const Mod_Int &x) {return *this = *this / x;}
	Mod_Int operator ^= (const Mod_Int &x) {return *this = Pow(*this, x.val);}
	Mod_Int operator <<= (const int &x) {return *this = *this << x;}

	Mod_Int operator ++(int) {
		val++;
		if (val >= kMod) val -= kMod;
		return *this;
	}
	Mod_Int operator --(int) {
		val--;
		if (val < 0) val += kMod;
		return *this;
	}

	bool operator < (const Mod_Int &x) const {return val < x.val;}
	bool operator > (const Mod_Int &x) const {return val > x.val;}
	bool operator <= (const Mod_Int &x) const {return val <= x.val;}
	bool operator >= (const Mod_Int &x) const {return val >= x.val;}
	bool operator == (const Mod_Int &x) const {return val == x.val;}
	bool operator != (const Mod_Int &x) const {return val != x.val;}

	void out() const {printf("%d", val);}
};

using Mint = Mod_Int<kMod>;

namespace Factorial {
	Mint *f, *inf;
	bool preprocessed_factorial;
	void Pre_Factorial(const int &sz) {
		if (preprocessed_factorial) return ;
		preprocessed_factorial = true;
		f = new Mint[sz + 1];
		inf = new Mint[sz + 1];
		f[0] = f[1] = inf[0] = inf[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		inf[sz] = f[sz].inv();
		for (int i = sz; i > 2; i--) inf[i - 1] = inf[i] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] * inf[m];}
	inline Mint C(const int &n, const int &m) {return f[n] * inf[m] * inf[n - m];}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] * inf[m] * inf[n - 1];}
	inline Mint Catalan(const int &n) {return f[n << 1] * inf[n] * inf[n + 1];}
}

namespace Factorial_No_Inf {
	Mint *f;
	void Pre_Factorial(const int &sz) {
		f = new Mint[sz + 1];
		f[0] = f[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] / f[m];}
	inline Mint C(const int &n, const int &m) {return f[n] / (f[m] * f[n - m]);}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] / (f[m] * f[n - 1]);}
	inline Mint Catalan(const int &n) {return f[n << 1] / (f[n] * f[n + 1]);}
}

namespace Inverse {
	using namespace Factorial;
	Mint *inv;
	void Pre_Inverse(const int &sz) {
		inv = new Mint[sz + 1];
		inv[1] = 1;
		Pre_Factorial(sz);
		for (int i = 1; i <= sz; i++) inv[i] = f[i - 1] * inf[i];
		return ;
	}
};
// End of C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix_fixed_size.cpp
namespace Matrix_Inner {
	template <typename T> T ABS(T x) {return x >= 0 ? x : -x;}
	bool IsZero(double x) {
		static constexpr double kEps = 1E-10;
		return ABS(x) <= kEps;
	}
	template <typename T> bool IsZero(T x) {return x == 0;}
}

template <typename T, int kN> struct Matrix {
	T val[kN][kN];
	int _size;

	Matrix() : _size(0) {}
	Matrix(int x, T v = 0) {
		_size = x;
		for (int i = 0; i < _size; i++) {
			memset(val[i], 0, sizeof(T) * _size);
			val[i][i] = v;
		}
	}

	void resize(int x) {
		_size = x;
		for (int i = 0; i < _size; i++) memset(val[i], 0, sizeof(T) * _size);
		return ;
	}
	int size() const {return _size;}

	Matrix operator = (const Matrix &x) {
		_size = x._size;
		for (int i = 0; i < _size; i++) memcpy(val[i], x[i], sizeof(T) * _size);
		return *this;
	}
	T* operator [](int x) {return val[x];}
	const T* operator [](int x) const {return val[x];}

	Matrix operator + (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] + x[i][j];
		return ans;
	}
	Matrix operator - (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] - x[i][j];
		return ans;
	}
	Matrix operator * (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator * (const Matrix &x) const {
		static constexpr int kCacheSize = 8 * 1024 * 1024 * sizeof(bool);
		static constexpr int kT = (1 << (__lg(kCacheSize) >> 1)) / sizeof(T);
		Matrix ans(_size);
		for (int I = 0; I < _size; I += kT) for (int J = 0; J < _size; J += kT) for (int K = 0; K < _size; K += kT) {
			int limi = min(I + kT, _size), limj = min(J + kT, _size), limk = min(K + kT, _size);
			for (int i = I; i < limi; i++) for (int j = J; j < limj; j++) {
				T sum = 0;
				for (int k = K; k < limk; k++) sum += val[i][k] * x[k][j];
				ans[i][j] += sum;
			}
		}
		return ans;
	}
	Matrix operator / (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator += (const Matrix &x) {return *this = *this + x;}
	Matrix operator -= (const Matrix &x) {return *this = *this - x;}
	Matrix operator *= (const T &x) {return *this = *this * x;}
	Matrix operator *= (const Matrix &x) {return *this = *this * x;}
	Matrix operator /= (const T &x) {return *this = *this / x;}

	T det() const {
		Matrix tmp = *this;
		bool flip = false;
		for (int i = 0; i < _size; i++) {
			if (Matrix_Inner::IsZero(tmp[i][i])) {
				int id = -1;
				for (int j = i + 1; j < _size; j++) if (!Matrix_Inner::IsZero(tmp[j][i])) {
					id = j;
					break;
				}
				if (id == -1) return 0;
				for (int j = i; j < _size; j++) swap(tmp[i][j], tmp[id][j]);
				flip = !flip;
			}

			for (int j = i + 1; j < _size; j++) if (!Matrix_Inner::IsZero(tmp[j][i])) {
				T freq(tmp[j][i] / tmp[i][i]);
				for (int k = i; k < _size; k++) tmp[j][k] -= freq * tmp[i][k];
			}
		}

		T ans = (flip ? -1 : 1);
		for (int i = 0; i < _size; i++) ans *= tmp[i][i];
		return ans;
	}

	T det_piviting() const {
		// !!! not finished
		return 0;
	}

	void out() const {
		for (int i = 0; i < _size; i++, printf("\n")) for (int j = 0; j < _size; j++) printf("%5d", val[i][j]);
		return ;
	}
};

template <typename T1, int kN, typename T2> Matrix<T1, kN> Pow(Matrix<T1, kN> A, T2 b) {
	Matrix<T1, kN> ans(A.size(), 1);
	for (; b; b >>= 1, A *= A) if (b & 1) ans *= A;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix_fixed_size.cpp

string s[kN];
int idx[kN][kN][kN];
int len[kN];
Matrix<Mint, kN> A;

int main() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> s[i];

	for (int i = 1; i <= n; i++) len[i] = int(s[i].size());

	constexpr int kLen = 5;

	int cur = 0;
	// idx : lst s, len diff, wait

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 0; k < kLen; k++)
		idx[i][j][k] = cur++;

	for (int i = 0; i < kLen; i++) idx[0][0][i] = cur++;

	A.resize(cur);

	for (int i = 1; i <= n; i++) A.val[idx[0][0][len[i] - 1]][idx[0][0][0]]++;

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k < kLen; k++)
		A.val[idx[i][j][k - 1]][idx[i][j][k]]++;

	for (int i = 1; i < kLen; i++) A.val[idx[0][0][i - 1]][idx[0][0][i]]++;

	auto match = [&](int x, int idx, int y, int idy, int len) -> bool {
		for (int i = 0; i < len; i++) if (s[x][idx + i] != s[y][idy + i]) return false;
		return true;
	};

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k <= n; k++) {
		int mn = min(j, len[k]);
		if (!match(i, len[i] - j, k, 0, mn)) continue;

		if (len[k] == j) A.val[idx[0][0][j - 1]][idx[i][j][0]]++;
		else if (len[k] < j) A.val[idx[i][j - len[k]][len[k] - 1]][idx[i][j][0]]++;
		else A.val[idx[k][len[k] - j][j - 1]][idx[i][j][0]]++;
	}

	for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) {
		int mn = min(len[i], len[j]);
		if (match(i, 0, j, 0, mn)) {
			if (len[i] < len[j]) A.val[idx[j][len[j] - len[i]][mn - 1]][idx[0][0][0]] += 2;
			else A.val[idx[i][len[i] - len[j]][mn - 1]][idx[0][0][0]] += 2;
		}
	}

	Mint ans = Pow(A, m)[idx[0][0][0]][idx[0][0][0]];
	printf("%d\n", ans);
}
// End of test.cpp

// Exported by Exporter.exe

// Included from test.cpp
// cf 1511 F
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define F first
#define S second
#define MP make_pair
#define MTP make_tuple
#define R Read
#define RD Read_Digit
#define RP Read_P
#define RL Read_Loop
#define RLD Read_Loop_Digit
#define RLP Read_Loop_P
#ifdef ONLINE_JUDGE
	#define Debug(x) ;
	#define Debugln(x) ;
	#define Debug_Array(n,x) ;
	#define Debugln_Array(n,x) ;
	#define NL ;
#else
	#define Debug(x) printf("%s :", (#x)); _Debug(x)
	#define Debugln(x) printf("%s :", (#x)); _Debugln(x)
	#define Debug_Array(n,x) printf("%s :", (#x)); _Debug_Array((n), (x))
	#define Debugln_Array(n,x) printf("%s :", (#x)); _Debugln_Array((n), (x))
	#define NL printf("\n")
#endif
typedef long long int ll;
typedef unsigned long long int ull;

constexpr int kN = 170;
constexpr int kMod = 998244353;
// constexpr int kMod = int(1E9 + 7);
// constexpr int kInf = 0x3f3f3f3f;
// constexpr ll kInf = 0x3f3f3f3f3f3f3f3f;
// constexpr double kPi = acos(-1);
// constexpr double kEps = 1E-9;

// Included from C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp
// --- Get ---
static inline char Get_Raw_Char() {
	static char buf[1 << 16], *p = buf, *end = buf;
	if (p == end) {
		if ((end = buf + fread(buf, 1, 1 << 16, stdin)) == buf) return '\0';
		p = buf;
	}
	return *p++;
}

// --- Read ---
template <typename T> static inline void Read_P(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	return ;
}

template <typename T> static inline void Read(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	if (neg) n = -n;
	return ;
}

template <typename T> static inline void Read_Digit(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	return ;
}

// --- Read multiple ---
template <typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read(n); return Read(Fargs...);}
template <typename T, typename... Targs> static inline void Read_Digit(T &n, Targs&... Fargs) {Read_Digit(n); return Read_Digit(Fargs...);}
template <typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P(n); return Read_P(Fargs...);}

// --- Read Loop ---
template <typename T> static inline void Read_Loop_i(int i, T *a) {return Read(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_i(int i, T *a, Targs*... Fargs) {Read(a[i]); return Read_Loop_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_Digit_i(int i, T *a) {return Read_Digit(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_Digit_i(int i, T *a, Targs*... Fargs) {Read_Digit(a[i]); return Read_Loop_Digit_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_Digit(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_Digit_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_P_i(int i, T *a) {return Read_P(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_P_i(int i, T *a, Targs*... Fargs) {Read_P(a[i]); return Read_Loop_P_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_P(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_P_i(i, Fargs...);}

// --- Float ---
template <int mul, typename T> static inline void Read(T &n) {
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;

	if (neg) n = -n;
	return ;
}

template <int mul, typename T> static inline void Read_P(T &n) {
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;

	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;
	return ;
}

template <int mul, typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read<mul>(n); return Read<mul>(Fargs...);}
template <int mul, typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P<mul>(n); return Read_P<mul>(Fargs...);}

// --- init ---
inline void IOS() {ios::sync_with_stdio(false); cin.tie(0);}
inline void Freopen(const char *in, const char *out) {freopen(in, "r", stdin); freopen(out, "w", stdout);}

// --- Output ---
template <typename T> void Print(T x) {
	if (x < 0) {
		printf("-");
		x = -x;
	}
	if (x == 0) printf("0");
	else {
		static int val[100];
		int idx = -1;
		while (x) {
			val[++idx] = x % 10;
			x /= 10;
		}
		while (idx >= 0) printf("%d", val[idx--]);
	}
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp
template <typename T> inline void sort(vector<T> &v) {return sort(v.begin(), v.end());}
template <typename T> inline void sort_r(vector<T> &v) {return sort(v.begin(), v.end(), greater<T>());}

template <typename T> inline void reverse(vector<T> &v) {return reverse(v.begin(), v.end());}

template <typename T> inline void Merge(vector<T> &a, vector<T> &b, vector<T> &c) {
	if (c.size() < a.size() + b.size()) c.resize(a.size() + b.size());
	merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
	return ;
}

template <typename T> inline void Discrete(vector<T> &v) {sort(v); v.resize(unique(v.begin(), v.end()) - v.begin());}

template <typename T> using PQ = priority_queue<T>;
template <typename T> using PQ_R = priority_queue<T, vector<T>, greater<T>>;

template <typename T> inline T ABS(T n) {return n >= 0 ? n : -n;}
template <typename T> inline T gcd(T a, T b) {return b ? gcd(b, a % b) : a;}
template <typename T> inline T lcm(T a, T b) {return a * b / gcd(a, b);}
template <typename T, typename... Targs> inline T min(T a, T b, T c, Targs... args) {return min(a, min(b, c, args...));}
template <typename T, typename... Targs> inline T max(T a, T b, T c, Targs... args) {return max(a, max(b, c, args...));}
template <typename T, typename... Targs> inline void chmin(T &a, T b, Targs... args) {a = min(a, b, args...); return ;}
template <typename T, typename... Targs> inline void chmax(T &a, T b, Targs... args) {a = max(a, b, args...); return ;}

template <typename T> inline int Digit_Sum(T a) {
	int ans = 0;
	while (a) {
		ans += a % 10;
		a /= 10;
	}
	return ans;
}
template <typename T> inline int Num_Length(T a) {
	int ans = 1;
	while (a /= 10) ans++;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp
void _print(int x) {printf("%d", x);}
void _print(long long int x) {printf("%lld", x);}
void _print(double x) {printf("%lf", x);}
template <typename T> void _print(T x) {return x.out();}
template <typename T1, typename T2> void _print(pair<T1, T2> x) {printf("("); _print(x.first); printf(", "); _print(x.second); printf(")");}

template <typename T> void _Debug(T x) {_print(x); printf("\n");}
template <typename T> void _Debug(vector<T> v) {
	if (v.empty()) printf(" empty");
	else for (T i : v) printf(" "), _print(i);
	printf("\n");
}

template <typename T1, typename T2, typename T3> void _Debug(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf(" ");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf(" ");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf(" ");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf(" ");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(vector<T> v) {
	if (v.empty()) printf(" empty\n");
	else {
		for (T i : v) printf("\n"), _print(i);
		printf("\n");
	}
}

template <typename T1, typename T2, typename T3> void _Debugln(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf("\n");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf("\n");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf("\n");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf("\n");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debug_Array(int n, const T *x) {for (int i = 1; i <= n; i++) printf(" "), _print(x[i]); printf("\n");}
template <typename T> void _Debugln_Array(int n, const T *x) {printf("\n"); for (int i = 1; i <= n; i++) _print(x[i]), printf("\n");}
// End of C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp
// !!! Mod_Int<kMod> a = 1 or Mod_Int<kMod> a(1) checks if the value is valid (and is slow)
// !!! However, the following usage doesn't check if the value is valid
// !!! Mod_Int<kMod> a;
// !!! a = 1;
template <typename T1, typename T2> T1 Pow(T1 a, T2 b) {
	T1 ans(1);
	while (b) {
		if (b & 1) ans *= a;
		a *= a;
		b >>= 1;
	}
	return ans;
}

template <int kMod> struct Mod_Int {
	static constexpr int Mod() {return kMod;}

	int val;
	Mod_Int() : val(0) {}
	template <typename T> Mod_Int(const T &x) {
		val = x % kMod;
		if (val < 0) val += kMod;
	}

	Mod_Int operator = (const Mod_Int &x) {
		val = x.val;
		return *this;
	}

	template <typename T> Mod_Int operator = (const T &x) {
		val = x;
		return *this;
	}

	Mod_Int inv() const {return Pow(*this, kMod - 2);}

	Mod_Int operator + (const Mod_Int &x) const {
		Mod_Int ans(val + x.val);
		if (ans.val >= kMod) ans.val -= kMod;
		return ans;
	}
	Mod_Int operator - (const Mod_Int &x) const {
		Mod_Int ans(val - x.val);
		if (ans.val < 0) ans.val += kMod;
		return ans;
	}
	Mod_Int operator * (const Mod_Int &x) const {return Mod_Int(1LL * val * x.val % kMod);}
	Mod_Int operator / (const Mod_Int &x) const {return *this * x.inv();}
	Mod_Int operator ^ (const Mod_Int &x) const {return Pow(*this, x.val);}
	Mod_Int operator << (const int &x) const {return ((1LL * val) << x) % kMod;}

	Mod_Int operator += (const Mod_Int &x) {return *this = *this + x;}
	Mod_Int operator -= (const Mod_Int &x) {return *this = *this - x;}
	Mod_Int operator *= (const Mod_Int &x) {return *this = *this * x;}
	Mod_Int operator /= (const Mod_Int &x) {return *this = *this / x;}
	Mod_Int operator ^= (const Mod_Int &x) {return *this = Pow(*this, x.val);}
	Mod_Int operator <<= (const int &x) {return *this = *this << x;}

	Mod_Int operator ++(int) {
		val++;
		if (val >= kMod) val -= kMod;
		return *this;
	}
	Mod_Int operator --(int) {
		val--;
		if (val < 0) val += kMod;
		return *this;
	}

	bool operator < (const Mod_Int &x) const {return val < x.val;}
	bool operator > (const Mod_Int &x) const {return val > x.val;}
	bool operator <= (const Mod_Int &x) const {return val <= x.val;}
	bool operator >= (const Mod_Int &x) const {return val >= x.val;}
	bool operator == (const Mod_Int &x) const {return val == x.val;}
	bool operator != (const Mod_Int &x) const {return val != x.val;}

	void out() const {printf("%d", val);}
};

using Mint = Mod_Int<kMod>;

namespace Factorial {
	Mint *f, *inf;
	bool preprocessed_factorial;
	void Pre_Factorial(const int &sz) {
		if (preprocessed_factorial) return ;
		preprocessed_factorial = true;
		f = new Mint[sz + 1];
		inf = new Mint[sz + 1];
		f[0] = f[1] = inf[0] = inf[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		inf[sz] = f[sz].inv();
		for (int i = sz; i > 2; i--) inf[i - 1] = inf[i] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] * inf[m];}
	inline Mint C(const int &n, const int &m) {return f[n] * inf[m] * inf[n - m];}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] * inf[m] * inf[n - 1];}
	inline Mint Catalan(const int &n) {return f[n << 1] * inf[n] * inf[n + 1];}
}

namespace Factorial_No_Inf {
	Mint *f;
	void Pre_Factorial(const int &sz) {
		f = new Mint[sz + 1];
		f[0] = f[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] / f[m];}
	inline Mint C(const int &n, const int &m) {return f[n] / (f[m] * f[n - m]);}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] / (f[m] * f[n - 1]);}
	inline Mint Catalan(const int &n) {return f[n << 1] / (f[n] * f[n + 1]);}
}

namespace Inverse {
	using namespace Factorial;
	Mint *inv;
	void Pre_Inverse(const int &sz) {
		inv = new Mint[sz + 1];
		inv[1] = 1;
		Pre_Factorial(sz);
		for (int i = 1; i <= sz; i++) inv[i] = f[i - 1] * inf[i];
		return ;
	}
};
// End of C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix_fixed_size.cpp
namespace Matrix_Inner {
	template <typename T> T ABS(T x) {return x >= 0 ? x : -x;}
	bool IsZero(double x) {
		static constexpr double kEps = 1E-10;
		return ABS(x) <= kEps;
	}
	template <typename T> bool IsZero(T x) {return x == 0;}
}

template <typename T, int kN> struct Matrix {
	T val[kN][kN];
	int _size;

	Matrix() : _size(0) {}
	Matrix(int x, T v = 0) {
		_size = x;
		for (int i = 0; i < _size; i++) {
			memset(val[i], 0, sizeof(T) * _size);
			val[i][i] = v;
		}
	}

	void resize(int x) {
		_size = x;
		for (int i = 0; i < _size; i++) memset(val[i], 0, sizeof(T) * _size);
		return ;
	}
	int size() const {return _size;}

	Matrix operator = (const Matrix &x) {
		_size = x._size;
		for (int i = 0; i < _size; i++) memcpy(val[i], x[i], sizeof(T) * _size);
		return *this;
	}
	T* operator [](int x) {return val[x];}
	const T* operator [](int x) const {return val[x];}

	Matrix operator + (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] + x[i][j];
		return ans;
	}
	Matrix operator - (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] - x[i][j];
		return ans;
	}
	Matrix operator * (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator * (const Matrix &x) const {
		static constexpr int kCacheSize = 8 * 1024 * 1024 * sizeof(bool);
		static constexpr int kT = (1 << (__lg(kCacheSize) >> 1)) / sizeof(T);
		Matrix ans(_size);
		for (int I = 0; I < _size; I += kT) for (int J = 0; J < _size; J += kT) for (int K = 0; K < _size; K += kT) {
			int limi = min(I + kT, _size), limj = min(J + kT, _size), limk = min(K + kT, _size);
			for (int i = I; i < limi; i++) for (int j = J; j < limj; j++) {
				T sum = 0;
				for (int k = K; k < limk; k++) sum += val[i][k] * x[k][j];
				ans[i][j] += sum;
			}
		}
		return ans;
	}
	Matrix operator / (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator += (const Matrix &x) {return *this = *this + x;}
	Matrix operator -= (const Matrix &x) {return *this = *this - x;}
	Matrix operator *= (const T &x) {return *this = *this * x;}
	Matrix operator *= (const Matrix &x) {return *this = *this * x;}
	Matrix operator /= (const T &x) {return *this = *this / x;}

	T det() const {
		Matrix tmp = *this;
		bool flip = false;
		for (int i = 0; i < _size; i++) {
			if (Matrix_Inner::IsZero(tmp[i][i])) {
				int id = -1;
				for (int j = i + 1; j < _size; j++) if (!Matrix_Inner::IsZero(tmp[j][i])) {
					id = j;
					break;
				}
				if (id == -1) return 0;
				for (int j = i; j < _size; j++) swap(tmp[i][j], tmp[id][j]);
				flip = !flip;
			}

			for (int j = i + 1; j < _size; j++) if (!Matrix_Inner::IsZero(tmp[j][i])) {
				T freq(tmp[j][i] / tmp[i][i]);
				for (int k = i; k < _size; k++) tmp[j][k] -= freq * tmp[i][k];
			}
		}

		T ans = (flip ? -1 : 1);
		for (int i = 0; i < _size; i++) ans *= tmp[i][i];
		return ans;
	}

	T det_piviting() const {
		// !!! not finished
		return 0;
	}

	void out() const {
		for (int i = 0; i < _size; i++, printf("\n")) for (int j = 0; j < _size; j++) printf("%5d", val[i][j]);
		return ;
	}
};

template <typename T1, int kN, typename T2> Matrix<T1, kN> Pow(Matrix<T1, kN> A, T2 b) {
	Matrix<T1, kN> ans(A.size(), 1);
	for (; b; b >>= 1, A *= A) if (b & 1) ans *= A;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix_fixed_size.cpp

string s[kN];
int idx[kN][kN][kN];
int len[kN];
Matrix<Mint, kN> A;

int main() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> s[i];

	for (int i = 1; i <= n; i++) len[i] = int(s[i].size());

	constexpr int kLen = 5;

	int cur = 0;
	// idx : lst s, len diff, wait

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 0; k < kLen; k++)
		idx[i][j][k] = cur++;

	for (int i = 0; i < kLen; i++) idx[0][0][i] = cur++;

	A.resize(cur);

	for (int i = 1; i <= n; i++) A.val[idx[0][0][len[i] - 1]][idx[0][0][0]]++;

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k < kLen; k++)
		A.val[idx[i][j][k - 1]][idx[i][j][k]]++;

	for (int i = 1; i < kLen; i++) A.val[idx[0][0][i - 1]][idx[0][0][i]]++;

	auto match = [&](int x, int idx, int y, int idy, int len) -> bool {
		for (int i = 0; i < len; i++) if (s[x][idx + i] != s[y][idy + i]) return false;
		return true;
	};

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k <= n; k++) {
		int mn = min(j, len[k]);
		if (!match(i, len[i] - j, k, 0, mn)) continue;

		if (len[k] == j) A.val[idx[0][0][j - 1]][idx[i][j][0]]++;
		else if (len[k] < j) A.val[idx[i][j - len[k]][len[k] - 1]][idx[i][j][0]]++;
		else A.val[idx[k][len[k] - j][j - 1]][idx[i][j][0]]++;
	}

	for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) {
		int mn = min(len[i], len[j]);
		if (match(i, 0, j, 0, mn)) {
			if (len[i] < len[j]) A.val[idx[j][len[j] - len[i]][mn - 1]][idx[0][0][0]] += 2;
			else A.val[idx[i][len[i] - len[j]][mn - 1]][idx[0][0][0]] += 2;
		}
	}

	Mint ans = Pow(A, m)[idx[0][0][0]][idx[0][0][0]];
	printf("%d\n", ans);
}
// End of test.cpp

#include <bits/stdc++.h>
using namespace std;

#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

#define INF 2000000000
#define INFL 200000000000000000LL

typedef long long int ll;
typedef pair<ll,ll> ii;
typedef pair<ii,ll> iii;
typedef vector<ll> vi;
typedef vector<ii> vii;

#define getbit(n,i) (((n)&(1LL<<(i)))!=0)
#define setbit0(n,i) ((n)&(~(1LL<<(i))))
#define setbit1(n,i) ((n)|(1LL<<(i)))
#define lastone(n) ((n)&(-(n)))

#define fi first
#define se second
#define PI (acos(-1))
#define mod (998244353)

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template<class T,class V> ostream& operator<<(ostream &s,pair<T,V> a)
{
    s<<a.fi<<' '<<a.se;
    return s;
}

const int N = 300, K = 2e3+3;

ll a[N][N],b[N][N],r[N][N],pr[N][N];
void mul(int m,ll md){
    for(int i=0;i<m;i++){
        for(int j=0;j<m;j++){
            __int128 p=0;
            for(int k=0;k<m;k++)p=(p+a[i][k]*b[k][j]);
            r[i][j]=p%md;
        }
    }
}
void POWER(int m,ll n,ll md){
    memset(pr,0,sizeof pr);
    for(int i=0;i<m;i++)pr[i][i]=1;
    while(n){
        if(n&1){
            for(int i=0;i<m;i++)for(int j=0;j<m;j++)a[i][j] = pr[i][j];
            mul(m,md);
            for(int i=0;i<m;i++)for(int j=0;j<m;j++)pr[i][j] = r[i][j];
        }
        n>>=1;
        if(n){
            for(int i=0;i<m;i++)for(int j=0;j<m;j++)a[i][j] = b[i][j];
            mul(m,md);
            for(int i=0;i<m;i++)for(int j=0;j<m;j++)b[i][j] = r[i][j];

        }
    }
}

struct vertex
{
    int next[26];
    int en;
    vertex()
    {
        fill(next,next+26,-1);
        en=0;
    }
};
vector<vertex> trie(1);
void add_string(string &s)
{
    int v=0;
    for(char ch:s)
    {
        ch-='a';
        if(trie[v].next[ch]==-1)
        {
            trie[v].next[ch]=trie.size();
            trie.emplace_back();
        }
        v=trie[v].next[ch];
    }
    trie[v].en++;
}
int vis[K][K];
int cnt = 0;
int dfs(int x,int y){
	if(vis[x][y]!=-1)return vis[x][y];
	int cur = vis[x][y] = cnt++;
	for(int c = 0;c<26;c++){
		if(trie[x].next[c]==-1||trie[y].next[c]==-1)continue;
		int l = trie[x].next[c];
		int l2 = trie[y].next[c];
		int p = dfs(l,l2);
		b[cur][p]++;
		if(trie[l].en){
			p = dfs(0,l2);
			b[cur][p]++;
		}

		if(trie[l2].en){
			p = dfs(l,0);
			b[cur][p]++;
		}

		if(trie[l].en&&trie[l2].en){
			p = dfs(0,0);
			b[cur][p]++;
		}
	}
	return cur;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    int T=1;
    //scanf("%d",&T);

    for(int qq=1; qq<=T; qq++)
    {
		int n,m;
		cin>>n>>m;
		for(int i=0;i<n;i++){
			string s;
			cin>>s;
			add_string(s);
		}
		memset(vis,-1,sizeof vis);
		dfs(0,0);
		POWER(cnt,m,mod);
		cout<<pr[0][0]<<endl;
    }
}

// Exported by Exporter.exe

// Included from test.cpp
// cf 1511 F
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define F first
#define S second
#define MP make_pair
#define MTP make_tuple
#define R Read
#define RD Read_Digit
#define RP Read_P
#define RL Read_Loop
#define RLD Read_Loop_Digit
#define RLP Read_Loop_P
#ifdef ONLINE_JUDGE
	#define Debug(x) ;
	#define Debugln(x) ;
	#define Debug_Array(n,x) ;
	#define Debugln_Array(n,x) ;
	#define NL ;
#else
	#define Debug(x) printf("%s :", (#x)); _Debug(x)
	#define Debugln(x) printf("%s :", (#x)); _Debugln(x)
	#define Debug_Array(n,x) printf("%s :", (#x)); _Debug_Array((n), (x))
	#define Debugln_Array(n,x) printf("%s :", (#x)); _Debugln_Array((n), (x))
	#define NL printf("\n")
#endif
typedef long long int ll;
typedef unsigned long long int ull;

constexpr int kN = 170;
constexpr int kMod = 998244353;
// constexpr int kMod = int(1E9 + 7);
// constexpr int kInf = 0x3f3f3f3f;
// constexpr ll kInf = 0x3f3f3f3f3f3f3f3f;
// constexpr double kPi = acos(-1);
// constexpr double kEps = 1E-9;

// Included from C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp
// --- Get ---
static inline char Get_Raw_Char() {
	static char buf[1 << 16], *p = buf, *end = buf;
	if (p == end) {
		if ((end = buf + fread(buf, 1, 1 << 16, stdin)) == buf) return '\0';
		p = buf;
	}
	return *p++;
}

// --- Read ---
template <typename T> static inline void Read_P(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	return ;
}

template <typename T> static inline void Read(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	if (neg) n = -n;
	return ;
}

template <typename T> static inline void Read_Digit(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	return ;
}

// --- Read multiple ---
template <typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read(n); return Read(Fargs...);}
template <typename T, typename... Targs> static inline void Read_Digit(T &n, Targs&... Fargs) {Read_Digit(n); return Read_Digit(Fargs...);}
template <typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P(n); return Read_P(Fargs...);}

// --- Read Loop ---
template <typename T> static inline void Read_Loop_i(int i, T *a) {return Read(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_i(int i, T *a, Targs*... Fargs) {Read(a[i]); return Read_Loop_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_Digit_i(int i, T *a) {return Read_Digit(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_Digit_i(int i, T *a, Targs*... Fargs) {Read_Digit(a[i]); return Read_Loop_Digit_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_Digit(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_Digit_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_P_i(int i, T *a) {return Read_P(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_P_i(int i, T *a, Targs*... Fargs) {Read_P(a[i]); return Read_Loop_P_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_P(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_P_i(i, Fargs...);}

// --- Float ---
template <int mul, typename T> static inline void Read(T &n) {
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;

	if (neg) n = -n;
	return ;
}

template <int mul, typename T> static inline void Read_P(T &n) {
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;

	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;
	return ;
}

template <int mul, typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read<mul>(n); return Read<mul>(Fargs...);}
template <int mul, typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P<mul>(n); return Read_P<mul>(Fargs...);}

// --- init ---
inline void IOS() {ios::sync_with_stdio(false); cin.tie(0);}
inline void Freopen(const char *in, const char *out) {freopen(in, "r", stdin); freopen(out, "w", stdout);}

// --- Output ---
template <typename T> void Print(T x) {
	if (x < 0) {
		printf("-");
		x = -x;
	}
	if (x == 0) printf("0");
	else {
		static int val[100];
		int idx = -1;
		while (x) {
			val[++idx] = x % 10;
			x /= 10;
		}
		while (idx >= 0) printf("%d", val[idx--]);
	}
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp
template <typename T> inline void sort(vector<T> &v) {return sort(v.begin(), v.end());}
template <typename T> inline void sort_r(vector<T> &v) {return sort(v.begin(), v.end(), greater<T>());}

template <typename T> inline void reverse(vector<T> &v) {return reverse(v.begin(), v.end());}

template <typename T> inline void Merge(vector<T> &a, vector<T> &b, vector<T> &c) {
	if (c.size() < a.size() + b.size()) c.resize(a.size() + b.size());
	merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
	return ;
}

template <typename T> inline void Discrete(vector<T> &v) {sort(v); v.resize(unique(v.begin(), v.end()) - v.begin());}

template <typename T> using PQ = priority_queue<T>;
template <typename T> using PQ_R = priority_queue<T, vector<T>, greater<T>>;

template <typename T> inline T ABS(T n) {return n >= 0 ? n : -n;}
template <typename T> inline T gcd(T a, T b) {return b ? gcd(b, a % b) : a;}
template <typename T> inline T lcm(T a, T b) {return a * b / gcd(a, b);}
template <typename T, typename... Targs> inline T min(T a, T b, T c, Targs... args) {return min(a, min(b, c, args...));}
template <typename T, typename... Targs> inline T max(T a, T b, T c, Targs... args) {return max(a, max(b, c, args...));}
template <typename T> inline void chmin(T &a, T b) {a = min(a, b); return ;}
template <typename T> inline void chmax(T &a, T b) {a = max(a, b); return ;}
template <typename T, typename... Targs> inline void chmin(T &a, T b, T c, Targs... args) {a = min(a, min(b, c, args...)); return ;}
template <typename T, typename... Targs> inline void chmax(T &a, T b, T c, Targs... args) {a = max(a, max(b, c, args...)); return ;}

template <typename T> inline int Digit_Sum(T a) {
	int ans = 0;
	while (a) {
		ans += a % 10;
		a /= 10;
	}
	return ans;
}
template <typename T> inline int Num_Length(T a) {
	int ans = 1;
	while (a /= 10) ans++;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp
void _print(int x) {printf("%d", x);}
void _print(long long int x) {printf("%lld", x);}
void _print(double x) {printf("%lf", x);}
template <typename T> void _print(T x) {return x.out();}
template <typename T1, typename T2> void _print(pair<T1, T2> x) {printf("("); _print(x.first); printf(", "); _print(x.second); printf(")");}

template <typename T> void _Debug(T x) {_print(x); printf("\n");}
template <typename T> void _Debug(vector<T> v) {
	if (v.empty()) printf(" empty");
	else for (T i : v) printf(" "), _print(i);
	printf("\n");
}

template <typename T1, typename T2, typename T3> void _Debug(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf(" ");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf(" ");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf(" ");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf(" ");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(vector<T> v) {
	if (v.empty()) printf(" empty\n");
	else {
		for (T i : v) printf("\n"), _print(i);
		printf("\n");
	}
}

template <typename T1, typename T2, typename T3> void _Debugln(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf("\n");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf("\n");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf("\n");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf("\n");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debug_Array(int n, const T *x) {for (int i = 1; i <= n; i++) printf(" "), _print(x[i]); printf("\n");}
template <typename T> void _Debugln_Array(int n, const T *x) {printf("\n"); for (int i = 1; i <= n; i++) _print(x[i]), printf("\n");}
// End of C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp
template <typename T1, typename T2> T1 Pow(T1 a, T2 b) {
	T1 ans(1);
	while (b) {
		if (b & 1) ans *= a;
		a *= a;
		b >>= 1;
	}
	return ans;
}

template <int kMod> struct Mod_Int {
	constexpr static int Mod() {return kMod;}

	int val;
	Mod_Int() {val = 0;}
	template <typename T> Mod_Int(const T &x) {val = x;}
	template <int nMod> Mod_Int(const Mod_Int<nMod> &x) {val = x.val;}

	Mod_Int inv() const {return Pow(*this, kMod - 2);}

	Mod_Int operator + (const Mod_Int &x) const {
		Mod_Int ans(val + x.val);
		if (ans.val >= kMod) ans.val -= kMod;
		return ans;
	}
	Mod_Int operator - (const Mod_Int &x) const {
		Mod_Int ans(val - x.val);
		if (ans.val < 0) ans.val += kMod;
		return ans;
	}
	Mod_Int operator * (const Mod_Int &x) const {return Mod_Int(1LL * val * x.val % kMod);}
	Mod_Int operator / (const Mod_Int &x) const {return *this * x.inv();}
	Mod_Int operator ^ (const Mod_Int &x) const {return Pow(*this, x.val);}
	Mod_Int operator << (const int &x) const {return ((1LL * val) << x) % kMod;}

	Mod_Int operator += (const Mod_Int &x) {return *this = *this + x;}
	Mod_Int operator -= (const Mod_Int &x) {return *this = *this - x;}
	Mod_Int operator *= (const Mod_Int &x) {return *this = *this * x;}
	Mod_Int operator /= (const Mod_Int &x) {return *this = *this / x;}
	Mod_Int operator ^= (const Mod_Int &x) {return *this = Pow(*this, x.val);}
	Mod_Int operator <<= (const int &x) {return *this = *this << x;}

	Mod_Int operator ++(int) {
		val++;
		if (val >= kMod) val -= kMod;
		return *this;
	}
	Mod_Int operator --(int) {
		val--;
		if (val < 0) val += kMod;
		return *this;
	}

	bool operator < (const Mod_Int &x) const {return val < x.val;}
	bool operator > (const Mod_Int &x) const {return val > x.val;}
	bool operator <= (const Mod_Int &x) const {return val <= x.val;}
	bool operator >= (const Mod_Int &x) const {return val >= x.val;}
	bool operator == (const Mod_Int &x) const {return val == x.val;}
	bool operator != (const Mod_Int &x) const {return val != x.val;}

	void out() const {printf("%d", val);}
};

using Mint = Mod_Int<kMod>;

namespace Factorial {
	Mint *f, *inf;
	bool preprocessed_factorial;
	void Pre_Factorial(const int &sz) {
		if (preprocessed_factorial) return ;
		preprocessed_factorial = true;
		f = new Mint[sz + 1];
		inf = new Mint[sz + 1];
		f[0] = f[1] = inf[0] = inf[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		inf[sz] = f[sz].inv();
		for (int i = sz; i > 2; i--) inf[i - 1] = inf[i] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] * inf[m];}
	inline Mint C(const int &n, const int &m) {return f[n] * inf[m] * inf[n - m];}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] * inf[m] * inf[n - 1];}
	inline Mint Catalan(const int &n) {return f[n << 1] * inf[n] * inf[n + 1];}
}

namespace Factorial_No_Inf {
	Mint *f;
	void Pre_Factorial(const int &sz) {
		f = new Mint[sz + 1];
		f[0] = f[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] / f[m];}
	inline Mint C(const int &n, const int &m) {return f[n] / (f[m] * f[n - m]);}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] / (f[m] * f[n - 1]);}
	inline Mint Catalan(const int &n) {return f[n << 1] / (f[n] * f[n + 1]);}
}

namespace Inverse {
	using namespace Factorial;
	Mint *inv;
	void Pre_Inverse(const int &sz) {
		inv = new Mint[sz + 1];
		inv[1] = 1;
		Pre_Factorial(sz);
		for (int i = 1; i <= sz; i++) inv[i] = f[i - 1] * inf[i];
		return ;
	}
};
// End of C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix.cpp
template <typename T> struct Matrix {
	T **val;
	int _size;

	Matrix() : val(nullptr), _size(0) {}
	Matrix(int x, T v = 0) {
		_size = x;
		val = new T* [_size];
		for (int i = 0; i < _size; i++) {
			val[i] = new T [_size];
			memset(val[i], 0, sizeof(T) * _size);
			val[i][i] = v;
		}
	}

	void clear() {
		for (int i = 0; i < _size; i++) delete [] val[i];
		delete [] val;
		return ;
	}

	void resize(int x) {
		clear();
		_size = x;
		val = new T* [_size];
		for (int i = 0; i < _size; i++) {
			val[i] = new T [_size];
			memset(val[i], 0, sizeof(T) * _size);
		}
		return ;
	}
	int size() const {return _size;}

	Matrix operator = (const Matrix &x) {
		clear();
		val = x.val;
		_size = x._size;
		return *this;
	}
	T* operator [](int x) {return val[x];}
	T* operator [](int x) const {return val[x];}

	Matrix operator + (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] + x[i][j];
		return ans;
	}
	Matrix operator - (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] - x[i][j];
		return ans;
	}
	Matrix operator * (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator * (const Matrix &x) const {
		static constexpr int kCacheSize = 512 * 1024 * sizeof(bool);
		static constexpr int kT = (1 << (__lg(kCacheSize) >> 1)) / sizeof(T);
		Matrix ans(_size);
		for (int I = 0; I < _size; I += kT) for (int J = 0; J < _size; J += kT) for (int K = 0; K < _size; K += kT) {
			int limi = min(I + kT, _size), limj = min(J + kT, _size), limk = min(K + kT, _size);
			for (int i = I; i < limi; i++) for (int j = J; j < limj; j++) {
				T sum = 0;
				for (int k = K; k < limk; k++) sum += val[i][k] * x[k][j];
				ans[i][j] += sum;
			}
		}
		return ans;
	}
	Matrix operator / (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator += (const Matrix &x) {return *this = *this + x;}
	Matrix operator -= (const Matrix &x) {return *this = *this - x;}
	Matrix operator *= (const T &x) {return *this = *this * x;}
	Matrix operator *= (const Matrix &x) {return *this = *this * x;}
	Matrix operator /= (const T &x) {return *this = *this / x;}

	void out() const {
		for (int i = 0; i < _size; i++, printf("\n")) for (int j = 0; j < _size; j++) printf("%5d", val[i][j]);
		return ;
	}
};

template <typename T1, typename T2> Matrix<T1> Pow(Matrix<T1> A, T2 b) {
	Matrix<T1> ans(A.size(), 1);
	for (; b; b >>= 1, A *= A) if (b & 1) ans *= A;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix.cpp

string s[kN];
int idx[kN][kN][kN];
int len[kN];
Matrix<Mint> A;

int main() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> s[i];

	for (int i = 1; i <= n; i++) len[i] = int(s[i].size());

	constexpr int kLen = 5;

	int cur = 0;
	// idx : lst s, len diff, wait

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 0; k < kLen; k++)
		idx[i][j][k] = cur++;

	for (int i = 0; i < kLen; i++) idx[0][0][i] = cur++;

	A.resize(cur);

	for (int i = 1; i <= n; i++) A.val[idx[0][0][len[i] - 1]][idx[0][0][0]]++;

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k < kLen; k++)
		A.val[idx[i][j][k - 1]][idx[i][j][k]]++;

	for (int i = 1; i < kLen; i++) A.val[idx[0][0][i - 1]][idx[0][0][i]]++;

	auto match = [&](int x, int idx, int y, int idy, int len) -> bool {
		for (int i = 0; i < len; i++) if (s[x][idx + i] != s[y][idy + i]) return false;
		return true;
	};

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k <= n; k++) {
		int mn = min(j, len[k]);
		if (!match(i, len[i] - j, k, 0, mn)) continue;

		if (len[k] == j) A.val[idx[0][0][j - 1]][idx[i][j][0]]++;
		else if (len[k] < j) A.val[idx[i][j - len[k]][len[k] - 1]][idx[i][j][0]]++;
		else A.val[idx[k][len[k] - j][j - 1]][idx[i][j][0]]++;
	}

	for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) {
		int mn = min(len[i], len[j]);
		if (match(i, 0, j, 0, mn)) {
			if (len[i] < len[j]) A.val[idx[j][len[j] - len[i]][mn - 1]][idx[0][0][0]] += 2;
			else A.val[idx[i][len[i] - len[j]][mn - 1]][idx[0][0][0]] += 2;
		}
	}

	Mint ans = Pow(A, m)[idx[0][0][0]][idx[0][0][0]];
	printf("%d\n", ans);
}
// End of test.cpp

// Exported by Exporter.exe

// Included from test.cpp
// cf 1511 F
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define F first
#define S second
#define MP make_pair
#define MTP make_tuple
#define R Read
#define RD Read_Digit
#define RP Read_P
#define RL Read_Loop
#define RLD Read_Loop_Digit
#define RLP Read_Loop_P
#ifdef ONLINE_JUDGE
	#define Debug(x) ;
	#define Debugln(x) ;
	#define Debug_Array(n,x) ;
	#define Debugln_Array(n,x) ;
	#define NL ;
#else
	#define Debug(x) printf("%s :", (#x)); _Debug(x)
	#define Debugln(x) printf("%s :", (#x)); _Debugln(x)
	#define Debug_Array(n,x) printf("%s :", (#x)); _Debug_Array((n), (x))
	#define Debugln_Array(n,x) printf("%s :", (#x)); _Debugln_Array((n), (x))
	#define NL printf("\n")
#endif
typedef long long int ll;
typedef unsigned long long int ull;

constexpr int kN = 170;
constexpr int kMod = 998244353;
// constexpr int kMod = int(1E9 + 7);
// constexpr int kInf = 0x3f3f3f3f;
// constexpr ll kInf = 0x3f3f3f3f3f3f3f3f;
// constexpr double kPi = acos(-1);
// constexpr double kEps = 1E-9;

// Included from C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp
// --- Get ---
static inline char Get_Raw_Char() {
	static char buf[1 << 16], *p = buf, *end = buf;
	if (p == end) {
		if ((end = buf + fread(buf, 1, 1 << 16, stdin)) == buf) return '\0';
		p = buf;
	}
	return *p++;
}

// --- Read ---
template <typename T> static inline void Read_P(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	return ;
}

template <typename T> static inline void Read(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	if (neg) n = -n;
	return ;
}

template <typename T> static inline void Read_Digit(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	return ;
}

// --- Read multiple ---
template <typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read(n); return Read(Fargs...);}
template <typename T, typename... Targs> static inline void Read_Digit(T &n, Targs&... Fargs) {Read_Digit(n); return Read_Digit(Fargs...);}
template <typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P(n); return Read_P(Fargs...);}

// --- Read Loop ---
template <typename T> static inline void Read_Loop_i(int i, T *a) {return Read(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_i(int i, T *a, Targs*... Fargs) {Read(a[i]); return Read_Loop_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_Digit_i(int i, T *a) {return Read_Digit(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_Digit_i(int i, T *a, Targs*... Fargs) {Read_Digit(a[i]); return Read_Loop_Digit_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_Digit(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_Digit_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_P_i(int i, T *a) {return Read_P(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_P_i(int i, T *a, Targs*... Fargs) {Read_P(a[i]); return Read_Loop_P_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_P(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_P_i(i, Fargs...);}

// --- Float ---
template <int mul, typename T> static inline void Read(T &n) {
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;

	if (neg) n = -n;
	return ;
}

template <int mul, typename T> static inline void Read_P(T &n) {
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;

	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;
	return ;
}

template <int mul, typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read<mul>(n); return Read<mul>(Fargs...);}
template <int mul, typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P<mul>(n); return Read_P<mul>(Fargs...);}

// --- init ---
inline void IOS() {ios::sync_with_stdio(false); cin.tie(0);}
inline void Freopen(const char *in, const char *out) {freopen(in, "r", stdin); freopen(out, "w", stdout);}

// --- Output ---
template <typename T> void Print(T x) {
	if (x < 0) {
		printf("-");
		x = -x;
	}
	if (x == 0) printf("0");
	else {
		static int val[100];
		int idx = -1;
		while (x) {
			val[++idx] = x % 10;
			x /= 10;
		}
		while (idx >= 0) printf("%d", val[idx--]);
	}
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp
template <typename T> inline void sort(vector<T> &v) {return sort(v.begin(), v.end());}
template <typename T> inline void sort_r(vector<T> &v) {return sort(v.begin(), v.end(), greater<T>());}

template <typename T> inline void reverse(vector<T> &v) {return reverse(v.begin(), v.end());}

template <typename T> inline void Merge(vector<T> &a, vector<T> &b, vector<T> &c) {
	if (c.size() < a.size() + b.size()) c.resize(a.size() + b.size());
	merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
	return ;
}

template <typename T> inline void Discrete(vector<T> &v) {sort(v); v.resize(unique(v.begin(), v.end()) - v.begin());}

template <typename T> using PQ = priority_queue<T>;
template <typename T> using PQ_R = priority_queue<T, vector<T>, greater<T>>;

template <typename T> inline T ABS(T n) {return n >= 0 ? n : -n;}
template <typename T> inline T gcd(T a, T b) {return b ? gcd(b, a % b) : a;}
template <typename T> inline T lcm(T a, T b) {return a * b / gcd(a, b);}
template <typename T, typename... Targs> inline T min(T a, T b, T c, Targs... args) {return min(a, min(b, c, args...));}
template <typename T, typename... Targs> inline T max(T a, T b, T c, Targs... args) {return max(a, max(b, c, args...));}
template <typename T> inline void chmin(T &a, T b) {a = min(a, b); return ;}
template <typename T> inline void chmax(T &a, T b) {a = max(a, b); return ;}
template <typename T, typename... Targs> inline void chmin(T &a, T b, T c, Targs... args) {a = min(a, min(b, c, args...)); return ;}
template <typename T, typename... Targs> inline void chmax(T &a, T b, T c, Targs... args) {a = max(a, max(b, c, args...)); return ;}

template <typename T> inline int Digit_Sum(T a) {
	int ans = 0;
	while (a) {
		ans += a % 10;
		a /= 10;
	}
	return ans;
}
template <typename T> inline int Num_Length(T a) {
	int ans = 1;
	while (a /= 10) ans++;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp
void _print(int x) {printf("%d", x);}
void _print(long long int x) {printf("%lld", x);}
void _print(double x) {printf("%lf", x);}
template <typename T> void _print(T x) {return x.out();}
template <typename T1, typename T2> void _print(pair<T1, T2> x) {printf("("); _print(x.first); printf(", "); _print(x.second); printf(")");}

template <typename T> void _Debug(T x) {_print(x); printf("\n");}
template <typename T> void _Debug(vector<T> v) {
	if (v.empty()) printf(" empty");
	else for (T i : v) printf(" "), _print(i);
	printf("\n");
}

template <typename T1, typename T2, typename T3> void _Debug(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf(" ");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf(" ");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf(" ");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf(" ");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(vector<T> v) {
	if (v.empty()) printf(" empty\n");
	else {
		for (T i : v) printf("\n"), _print(i);
		printf("\n");
	}
}

template <typename T1, typename T2, typename T3> void _Debugln(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf("\n");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf("\n");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf("\n");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf("\n");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debug_Array(int n, const T *x) {for (int i = 1; i <= n; i++) printf(" "), _print(x[i]); printf("\n");}
template <typename T> void _Debugln_Array(int n, const T *x) {printf("\n"); for (int i = 1; i <= n; i++) _print(x[i]), printf("\n");}
// End of C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp
template <typename T1, typename T2> T1 Pow(T1 a, T2 b) {
	T1 ans(1);
	while (b) {
		if (b & 1) ans *= a;
		a *= a;
		b >>= 1;
	}
	return ans;
}

template <int kMod> struct Mod_Int {
	constexpr static int Mod() {return kMod;}

	int val;
	Mod_Int() {val = 0;}
	template <typename T> Mod_Int(const T &x) {val = x;}
	template <int nMod> Mod_Int(const Mod_Int<nMod> &x) {val = x.val;}

	Mod_Int inv() const {return Pow(*this, kMod - 2);}

	Mod_Int operator + (const Mod_Int &x) const {
		Mod_Int ans(val + x.val);
		if (ans.val >= kMod) ans.val -= kMod;
		return ans;
	}
	Mod_Int operator - (const Mod_Int &x) const {
		Mod_Int ans(val - x.val);
		if (ans.val < 0) ans.val += kMod;
		return ans;
	}
	Mod_Int operator * (const Mod_Int &x) const {return Mod_Int(1LL * val * x.val % kMod);}
	Mod_Int operator / (const Mod_Int &x) const {return *this * x.inv();}
	Mod_Int operator ^ (const Mod_Int &x) const {return Pow(*this, x.val);}
	Mod_Int operator << (const int &x) const {return ((1LL * val) << x) % kMod;}

	Mod_Int operator += (const Mod_Int &x) {return *this = *this + x;}
	Mod_Int operator -= (const Mod_Int &x) {return *this = *this - x;}
	Mod_Int operator *= (const Mod_Int &x) {return *this = *this * x;}
	Mod_Int operator /= (const Mod_Int &x) {return *this = *this / x;}
	Mod_Int operator ^= (const Mod_Int &x) {return *this = Pow(*this, x.val);}
	Mod_Int operator <<= (const int &x) {return *this = *this << x;}

	Mod_Int operator ++(int) {
		val++;
		if (val >= kMod) val -= kMod;
		return *this;
	}
	Mod_Int operator --(int) {
		val--;
		if (val < 0) val += kMod;
		return *this;
	}

	bool operator < (const Mod_Int &x) const {return val < x.val;}
	bool operator > (const Mod_Int &x) const {return val > x.val;}
	bool operator <= (const Mod_Int &x) const {return val <= x.val;}
	bool operator >= (const Mod_Int &x) const {return val >= x.val;}
	bool operator == (const Mod_Int &x) const {return val == x.val;}
	bool operator != (const Mod_Int &x) const {return val != x.val;}

	void out() const {printf("%d", val);}
};

using Mint = Mod_Int<kMod>;

namespace Factorial {
	Mint *f, *inf;
	bool preprocessed_factorial;
	void Pre_Factorial(const int &sz) {
		if (preprocessed_factorial) return ;
		preprocessed_factorial = true;
		f = new Mint[sz + 1];
		inf = new Mint[sz + 1];
		f[0] = f[1] = inf[0] = inf[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		inf[sz] = f[sz].inv();
		for (int i = sz; i > 2; i--) inf[i - 1] = inf[i] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] * inf[m];}
	inline Mint C(const int &n, const int &m) {return f[n] * inf[m] * inf[n - m];}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] * inf[m] * inf[n - 1];}
	inline Mint Catalan(const int &n) {return f[n << 1] * inf[n] * inf[n + 1];}
}

namespace Factorial_No_Inf {
	Mint *f;
	void Pre_Factorial(const int &sz) {
		f = new Mint[sz + 1];
		f[0] = f[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] / f[m];}
	inline Mint C(const int &n, const int &m) {return f[n] / (f[m] * f[n - m]);}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] / (f[m] * f[n - 1]);}
	inline Mint Catalan(const int &n) {return f[n << 1] / (f[n] * f[n + 1]);}
}

namespace Inverse {
	using namespace Factorial;
	Mint *inv;
	void Pre_Inverse(const int &sz) {
		inv = new Mint[sz + 1];
		inv[1] = 1;
		Pre_Factorial(sz);
		for (int i = 1; i <= sz; i++) inv[i] = f[i - 1] * inf[i];
		return ;
	}
};
// End of C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix.cpp
template <typename T> struct Matrix {
	T **val;
	int _size;

	Matrix() : val(nullptr), _size(0) {}
	Matrix(int x, T v = 0) {
		_size = x;
		val = new T* [_size];
		for (int i = 0; i < _size; i++) {
			val[i] = new T [_size];
			memset(val[i], 0, sizeof(T) * _size);
			val[i][i] = v;
		}
	}

	void clear() {
		for (int i = 0; i < _size; i++) delete [] val[i];
		delete [] val;
		return ;
	}

	void resize(int x) {
		clear();
		_size = x;
		val = new T* [_size];
		for (int i = 0; i < _size; i++) {
			val[i] = new T [_size];
			memset(val[i], 0, sizeof(T) * _size);
		}
		return ;
	}
	int size() const {return _size;}

	Matrix operator = (const Matrix &x) {
		clear();
		val = x.val;
		_size = x._size;
		return *this;
	}
	T* operator [](int x) {return val[x];}
	T* operator [](int x) const {return val[x];}

	Matrix operator + (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] + x[i][j];
		return ans;
	}
	Matrix operator - (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] - x[i][j];
		return ans;
	}
	Matrix operator * (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator * (const Matrix &x) const {
		static constexpr int kCacheSize = 8 * 1024 * 1024 * sizeof(bool);
		static constexpr int kT = (1 << (__lg(kCacheSize) >> 1)) / sizeof(T);
		Matrix ans(_size);
		for (int I = 0; I < _size; I += kT) for (int J = 0; J < _size; J += kT) for (int K = 0; K < _size; K += kT) {
			int limi = min(I + kT, _size), limj = min(J + kT, _size), limk = min(K + kT, _size);
			for (int i = I; i < limi; i++) for (int j = J; j < limj; j++) {
				T sum = 0;
				for (int k = K; k < limk; k++) sum += val[i][k] * x[k][j];
				ans[i][j] += sum;
			}
		}
		return ans;
	}
	Matrix operator / (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator += (const Matrix &x) {return *this = *this + x;}
	Matrix operator -= (const Matrix &x) {return *this = *this - x;}
	Matrix operator *= (const T &x) {return *this = *this * x;}
	Matrix operator *= (const Matrix &x) {return *this = *this * x;}
	Matrix operator /= (const T &x) {return *this = *this / x;}

	void out() const {
		for (int i = 0; i < _size; i++, printf("\n")) for (int j = 0; j < _size; j++) printf("%5d", val[i][j]);
		return ;
	}
};

template <typename T1, typename T2> Matrix<T1> Pow(Matrix<T1> A, T2 b) {
	Matrix<T1> ans(A.size(), 1);
	for (; b; b >>= 1, A *= A) if (b & 1) ans *= A;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix.cpp

string s[kN];
int idx[kN][kN][kN];
int len[kN];
Matrix<Mint> A;

int main() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> s[i];

	for (int i = 1; i <= n; i++) len[i] = int(s[i].size());

	constexpr int kLen = 5;

	int cur = 0;
	// idx : lst s, len diff, wait

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 0; k < kLen; k++)
		idx[i][j][k] = cur++;

	for (int i = 0; i < kLen; i++) idx[0][0][i] = cur++;

	A.resize(cur);

	for (int i = 1; i <= n; i++) A.val[idx[0][0][len[i] - 1]][idx[0][0][0]]++;

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k < kLen; k++)
		A.val[idx[i][j][k - 1]][idx[i][j][k]]++;

	for (int i = 1; i < kLen; i++) A.val[idx[0][0][i - 1]][idx[0][0][i]]++;

	auto match = [&](int x, int idx, int y, int idy, int len) -> bool {
		for (int i = 0; i < len; i++) if (s[x][idx + i] != s[y][idy + i]) return false;
		return true;
	};

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k <= n; k++) {
		int mn = min(j, len[k]);
		if (!match(i, len[i] - j, k, 0, mn)) continue;

		if (len[k] == j) A.val[idx[0][0][j - 1]][idx[i][j][0]]++;
		else if (len[k] < j) A.val[idx[i][j - len[k]][len[k] - 1]][idx[i][j][0]]++;
		else A.val[idx[k][len[k] - j][j - 1]][idx[i][j][0]]++;
	}

	for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) {
		int mn = min(len[i], len[j]);
		if (match(i, 0, j, 0, mn)) {
			if (len[i] < len[j]) A.val[idx[j][len[j] - len[i]][mn - 1]][idx[0][0][0]] += 2;
			else A.val[idx[i][len[i] - len[j]][mn - 1]][idx[0][0][0]] += 2;
		}
	}

	Mint ans = Pow(A, m)[idx[0][0][0]][idx[0][0][0]];
	printf("%d\n", ans);
}
// End of test.cpp

#include<bits/stdc++.h>
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);i++)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);i--)
#define pii pair<int,int>
#define fi first
#define se second
#define PB push_back
#define ll long long
#define ull unsigned long long
#define pll pair<ll,ll>
#define y1 orzkcz
using namespace std;

const int mo=998244353;
int n,m,nd=1,md,ed[50],mi[50];
int ch[50][26],idx[50][50];

struct Mat{
	int a[563][563];
	Mat(){
		memset(a,0,sizeof(a));
	}
	Mat operator *(const Mat &b)const{
		Mat c;
		for (int i=1;i<=md;i++)
			for (int j=1;j<=md;j++)
				if (a[i][j])
					for (int k=1;k<=md;k++)
						c.a[i][k]=(c.a[i][k]+1ll*a[i][j]*b.a[j][k])%mo;
		return c;
	}
}tr,S;
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++){
		char s[16];
		scanf("%s",s+1);
		int x=1;
		for (int j=1;s[j];++j){
			if (!ch[x][s[j]-'a'])
				ch[x][s[j]-'a']=++nd;
			mi[x]=1;
			x=ch[x][s[j]-'a'];
		}
		ed[x]=1;
	}
	for (int i=1;i<=nd;i++)
		for (int j=i;j<=nd;j++)
			if (mi[i]&&mi[j]) idx[i][j]=++md;
	for (int i=1;i<=nd;i++)
		for (int j=i;j<=nd;j++)
			for (int c=0;c<=25;c++){
				if (!ch[i][c]||!ch[j][c]) continue;
				int ni=ch[i][c],nj=ch[j][c];
				++tr.a[idx[i][j]][idx[min(ni,nj)][max(ni,nj)]];
				if (ed[ni]) ++tr.a[idx[i][j]][idx[1][nj]];
				if (ed[nj]) ++tr.a[idx[i][j]][idx[1][ni]];
				if (ed[ni]&&ed[nj]) ++tr.a[idx[i][j]][idx[1][1]];
			}
	S=tr; --m;
	for (;m;m/=2,tr=tr*tr)
		if (m&1) S=S*tr;
	printf("%d\n",S.a[1][1]);
}

// Exported by Exporter.exe

// Included from test.cpp
// cf 1511 F
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define F first
#define S second
#define MP make_pair
#define MTP make_tuple
#define R Read
#define RD Read_Digit
#define RP Read_P
#define RL Read_Loop
#define RLD Read_Loop_Digit
#define RLP Read_Loop_P
#ifdef ONLINE_JUDGE
	#define Debug(x) ;
	#define Debugln(x) ;
	#define Debug_Array(n,x) ;
	#define Debugln_Array(n,x) ;
	#define NL ;
#else
	#define Debug(x) printf("%s :", (#x)); _Debug(x)
	#define Debugln(x) printf("%s :", (#x)); _Debugln(x)
	#define Debug_Array(n,x) printf("%s :", (#x)); _Debug_Array((n), (x))
	#define Debugln_Array(n,x) printf("%s :", (#x)); _Debugln_Array((n), (x))
	#define NL printf("\n")
#endif
typedef long long int ll;
typedef unsigned long long int ull;

constexpr int kN = 170;
constexpr int kMod = 998244353;
// constexpr int kMod = int(1E9 + 7);
// constexpr int kInf = 0x3f3f3f3f;
// constexpr ll kInf = 0x3f3f3f3f3f3f3f3f;
// constexpr double kPi = acos(-1);
// constexpr double kEps = 1E-9;

// Included from C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp
// --- Get ---
static inline char Get_Raw_Char() {
	static char buf[1 << 16], *p = buf, *end = buf;
	if (p == end) {
		if ((end = buf + fread(buf, 1, 1 << 16, stdin)) == buf) return '\0';
		p = buf;
	}
	return *p++;
}

// --- Read ---
template <typename T> static inline void Read_P(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	return ;
}

template <typename T> static inline void Read(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	if (neg) n = -n;
	return ;
}

template <typename T> static inline void Read_Digit(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	return ;
}

// --- Read multiple ---
template <typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read(n); return Read(Fargs...);}
template <typename T, typename... Targs> static inline void Read_Digit(T &n, Targs&... Fargs) {Read_Digit(n); return Read_Digit(Fargs...);}
template <typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P(n); return Read_P(Fargs...);}

// --- Read Loop ---
template <typename T> static inline void Read_Loop_i(int i, T *a) {return Read(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_i(int i, T *a, Targs*... Fargs) {Read(a[i]); return Read_Loop_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_Digit_i(int i, T *a) {return Read_Digit(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_Digit_i(int i, T *a, Targs*... Fargs) {Read_Digit(a[i]); return Read_Loop_Digit_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_Digit(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_Digit_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_P_i(int i, T *a) {return Read_P(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_P_i(int i, T *a, Targs*... Fargs) {Read_P(a[i]); return Read_Loop_P_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_P(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_P_i(i, Fargs...);}

// --- Float ---
template <int mul, typename T> static inline void Read(T &n) {
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;

	if (neg) n = -n;
	return ;
}

template <int mul, typename T> static inline void Read_P(T &n) {
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;

	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;
	return ;
}

template <int mul, typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read<mul>(n); return Read<mul>(Fargs...);}
template <int mul, typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P<mul>(n); return Read_P<mul>(Fargs...);}

// --- init ---
inline void IOS() {ios::sync_with_stdio(false); cin.tie(0);}
inline void Freopen(const char *in, const char *out) {freopen(in, "r", stdin); freopen(out, "w", stdout);}

// --- Output ---
template <typename T> void Print(T x) {
	if (x < 0) {
		printf("-");
		x = -x;
	}
	if (x == 0) printf("0");
	else {
		static int val[100];
		int idx = -1;
		while (x) {
			val[++idx] = x % 10;
			x /= 10;
		}
		while (idx >= 0) printf("%d", val[idx--]);
	}
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp
template <typename T> inline void sort(vector<T> &v) {return sort(v.begin(), v.end());}
template <typename T> inline void sort_r(vector<T> &v) {return sort(v.begin(), v.end(), greater<T>());}

template <typename T> inline void reverse(vector<T> &v) {return reverse(v.begin(), v.end());}

template <typename T> inline void Merge(vector<T> &a, vector<T> &b, vector<T> &c) {
	if (c.size() < a.size() + b.size()) c.resize(a.size() + b.size());
	merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
	return ;
}

template <typename T> inline void Discrete(vector<T> &v) {sort(v); v.resize(unique(v.begin(), v.end()) - v.begin());}

template <typename T> using PQ = priority_queue<T>;
template <typename T> using PQ_R = priority_queue<T, vector<T>, greater<T>>;

template <typename T> inline T ABS(T n) {return n >= 0 ? n : -n;}
template <typename T> inline T gcd(T a, T b) {return b ? gcd(b, a % b) : a;}
template <typename T> inline T lcm(T a, T b) {return a * b / gcd(a, b);}
template <typename T, typename... Targs> inline T min(T a, T b, T c, Targs... args) {return min(a, min(b, c, args...));}
template <typename T, typename... Targs> inline T max(T a, T b, T c, Targs... args) {return max(a, max(b, c, args...));}
template <typename T> inline void chmin(T &a, T b) {a = min(a, b); return ;}
template <typename T> inline void chmax(T &a, T b) {a = max(a, b); return ;}
template <typename T, typename... Targs> inline void chmin(T &a, T b, T c, Targs... args) {a = min(a, min(b, c, args...)); return ;}
template <typename T, typename... Targs> inline void chmax(T &a, T b, T c, Targs... args) {a = max(a, max(b, c, args...)); return ;}

template <typename T> inline int Digit_Sum(T a) {
	int ans = 0;
	while (a) {
		ans += a % 10;
		a /= 10;
	}
	return ans;
}
template <typename T> inline int Num_Length(T a) {
	int ans = 1;
	while (a /= 10) ans++;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp
void _print(int x) {printf("%d", x);}
void _print(long long int x) {printf("%lld", x);}
void _print(double x) {printf("%lf", x);}
template <typename T> void _print(T x) {return x.out();}
template <typename T1, typename T2> void _print(pair<T1, T2> x) {printf("("); _print(x.first); printf(", "); _print(x.second); printf(")");}

template <typename T> void _Debug(T x) {_print(x); printf("\n");}
template <typename T> void _Debug(vector<T> v) {
	if (v.empty()) printf(" empty");
	else for (T i : v) printf(" "), _print(i);
	printf("\n");
}

template <typename T1, typename T2, typename T3> void _Debug(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf(" ");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf(" ");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf(" ");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf(" ");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(vector<T> v) {
	if (v.empty()) printf(" empty\n");
	else {
		for (T i : v) printf("\n"), _print(i);
		printf("\n");
	}
}

template <typename T1, typename T2, typename T3> void _Debugln(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf("\n");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf("\n");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf("\n");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf("\n");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debug_Array(int n, const T *x) {for (int i = 1; i <= n; i++) printf(" "), _print(x[i]); printf("\n");}
template <typename T> void _Debugln_Array(int n, const T *x) {printf("\n"); for (int i = 1; i <= n; i++) _print(x[i]), printf("\n");}
// End of C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp
template <typename T1, typename T2> T1 Pow(T1 a, T2 b) {
	T1 ans(1);
	while (b) {
		if (b & 1) ans *= a;
		a *= a;
		b >>= 1;
	}
	return ans;
}

template <int kMod> struct Mod_Int {
	constexpr static int Mod() {return kMod;}

	int val;
	Mod_Int() {val = 0;}
	template <typename T> Mod_Int(const T &x) {val = x;}
	template <int nMod> Mod_Int(const Mod_Int<nMod> &x) {val = x.val;}

	Mod_Int inv() const {return Pow(*this, kMod - 2);}

	Mod_Int operator + (const Mod_Int &x) const {
		Mod_Int ans(val + x.val);
		if (ans.val >= kMod) ans.val -= kMod;
		return ans;
	}
	Mod_Int operator - (const Mod_Int &x) const {
		Mod_Int ans(val - x.val);
		if (ans.val < 0) ans.val += kMod;
		return ans;
	}
	Mod_Int operator * (const Mod_Int &x) const {return Mod_Int(1LL * val * x.val % kMod);}
	Mod_Int operator / (const Mod_Int &x) const {return *this * x.inv();}
	Mod_Int operator ^ (const Mod_Int &x) const {return Pow(*this, x.val);}
	Mod_Int operator << (const int &x) const {return ((1LL * val) << x) % kMod;}

	Mod_Int operator += (const Mod_Int &x) {return *this = *this + x;}
	Mod_Int operator -= (const Mod_Int &x) {return *this = *this - x;}
	Mod_Int operator *= (const Mod_Int &x) {return *this = *this * x;}
	Mod_Int operator /= (const Mod_Int &x) {return *this = *this / x;}
	Mod_Int operator ^= (const Mod_Int &x) {return *this = Pow(*this, x.val);}
	Mod_Int operator <<= (const int &x) {return *this = *this << x;}

	Mod_Int operator ++(int) {
		val++;
		if (val >= kMod) val -= kMod;
		return *this;
	}
	Mod_Int operator --(int) {
		val--;
		if (val < 0) val += kMod;
		return *this;
	}

	bool operator < (const Mod_Int &x) const {return val < x.val;}
	bool operator > (const Mod_Int &x) const {return val > x.val;}
	bool operator <= (const Mod_Int &x) const {return val <= x.val;}
	bool operator >= (const Mod_Int &x) const {return val >= x.val;}
	bool operator == (const Mod_Int &x) const {return val == x.val;}
	bool operator != (const Mod_Int &x) const {return val != x.val;}

	void out() const {printf("%d", val);}
};

using Mint = Mod_Int<kMod>;

namespace Factorial {
	Mint *f, *inf;
	bool preprocessed_factorial;
	void Pre_Factorial(const int &sz) {
		if (preprocessed_factorial) return ;
		preprocessed_factorial = true;
		f = new Mint[sz + 1];
		inf = new Mint[sz + 1];
		f[0] = f[1] = inf[0] = inf[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		inf[sz] = f[sz].inv();
		for (int i = sz; i > 2; i--) inf[i - 1] = inf[i] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] * inf[m];}
	inline Mint C(const int &n, const int &m) {return f[n] * inf[m] * inf[n - m];}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] * inf[m] * inf[n - 1];}
	inline Mint Catalan(const int &n) {return f[n << 1] * inf[n] * inf[n + 1];}
}

namespace Factorial_No_Inf {
	Mint *f;
	void Pre_Factorial(const int &sz) {
		f = new Mint[sz + 1];
		f[0] = f[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] / f[m];}
	inline Mint C(const int &n, const int &m) {return f[n] / (f[m] * f[n - m]);}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] / (f[m] * f[n - 1]);}
	inline Mint Catalan(const int &n) {return f[n << 1] / (f[n] * f[n + 1]);}
}

namespace Inverse {
	using namespace Factorial;
	Mint *inv;
	void Pre_Inverse(const int &sz) {
		inv = new Mint[sz + 1];
		inv[1] = 1;
		Pre_Factorial(sz);
		for (int i = 1; i <= sz; i++) inv[i] = f[i - 1] * inf[i];
		return ;
	}
};
// End of C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix.cpp
template <typename T> struct Matrix {
	T **val;
	int _size;

	Matrix() : val(nullptr), _size(0) {}
	Matrix(int x, T v = 0) {
		_size = x;
		val = new T* [_size];
		for (int i = 0; i < _size; i++) {
			val[i] = new T [_size];
			memset(val[i], 0, sizeof(T) * _size);
			val[i][i] = v;
		}
	}

	void del() {
		for (int i = 0; i < _size; i++) delete [] val[i];
		delete [] val;
		return ;
	}

	void resize(int x) {
		del();
		_size = x;
		val = new T* [_size];
		for (int i = 0; i < _size; i++) {
			val[i] = new T [_size];
			memset(val[i], 0, sizeof(T) * _size);
		}
		return ;
	}
	int size() const {return _size;}

	Matrix operator = (const Matrix &x) {
		del();
		val = x.val;
		_size = x._size;
		return *this;
	}
	T* operator [](int x) {return val[x];}
	T* operator [](int x) const {return val[x];}

	Matrix operator + (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] + x[i][j];
		return ans;
	}
	Matrix operator - (const Matrix &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] - x[i][j];
		return ans;
	}
	Matrix operator * (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator * (const Matrix &x) const {
		static constexpr int kCacheSize = 8 * 1024 * sizeof(bool);
		static constexpr int kT = (1 << (__lg(kCacheSize) >> 1)) / sizeof(T);
		Matrix ans(_size);
		for (int I = 0; I < _size; I += kT) for (int J = 0; J < _size; J += kT) for (int K = 0; K < _size; K += kT) {
			int limi = min(I + kT, _size), limj = min(J + kT, _size), limk = min(K + kT, _size);
			for (int i = I; i < limi; i++) for (int j = J; j < limj; j++) {
				T sum = 0;
				for (int k = K; k < limk; k++) sum += val[i][k] * x[k][j];
				ans[i][j] += sum;
			}
		}
		return ans;
	}
	Matrix operator / (const T &x) const {
		Matrix ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator += (const Matrix &x) {return *this = *this + x;}
	Matrix operator -= (const Matrix &x) {return *this = *this - x;}
	Matrix operator *= (const T &x) {return *this = *this * x;}
	Matrix operator *= (const Matrix &x) {return *this = *this * x;}
	Matrix operator /= (const T &x) {return *this = *this / x;}

	void out() const {
		for (int i = 0; i < _size; i++, printf("\n")) for (int j = 0; j < _size; j++) printf("%5d", val[i][j]);
		return ;
	}
};

template <typename T1, typename T2> Matrix<T1> Pow(Matrix<T1> A, T2 b) {
	Matrix<T1> ans(A.size(), 1);
	for (; b; b >>= 1, A *= A) if (b & 1) ans *= A;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix.cpp

string s[kN];
int idx[kN][kN][kN];
int len[kN];
Matrix<Mint> A;

int main() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> s[i];

	for (int i = 1; i <= n; i++) len[i] = int(s[i].size());

	constexpr int kLen = 5;

	int cur = 0;
	// idx : lst s, len diff, wait

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 0; k < kLen; k++)
		idx[i][j][k] = cur++;

	for (int i = 0; i < kLen; i++) idx[0][0][i] = cur++;

	A.resize(cur);

	for (int i = 1; i <= n; i++) A.val[idx[0][0][len[i] - 1]][idx[0][0][0]]++;

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k < kLen; k++)
		A.val[idx[i][j][k - 1]][idx[i][j][k]]++;

	for (int i = 1; i < kLen; i++) A.val[idx[0][0][i - 1]][idx[0][0][i]]++;

	auto match = [&](int x, int idx, int y, int idy, int len) -> bool {
		for (int i = 0; i < len; i++) if (s[x][idx + i] != s[y][idy + i]) return false;
		return true;
	};

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k <= n; k++) {
		int mn = min(j, len[k]);
		if (!match(i, len[i] - j, k, 0, mn)) continue;

		if (len[k] == j) A.val[idx[0][0][j - 1]][idx[i][j][0]]++;
		else if (len[k] < j) A.val[idx[i][j - len[k]][len[k] - 1]][idx[i][j][0]]++;
		else A.val[idx[k][len[k] - j][j - 1]][idx[i][j][0]]++;
	}

	for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) {
		int mn = min(len[i], len[j]);
		if (match(i, 0, j, 0, mn)) {
			if (len[i] < len[j]) A.val[idx[j][len[j] - len[i]][mn - 1]][idx[0][0][0]] += 2;
			else A.val[idx[i][len[i] - len[j]][mn - 1]][idx[0][0][0]] += 2;
		}
	}

	Mint ans = Pow(A, m)[idx[0][0][0]][idx[0][0][0]];
	printf("%d\n", ans);
}
// End of test.cpp

#include <bits/stdc++.h>

typedef long long ll;
typedef long double ld;
#define FASTIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define PRECISION cout << fixed << setprecision(20);

using namespace std;

const int K = 26;
const int mod = 998244353;
const int N = 250;

struct Mint {
    ll v; explicit operator ll() const { return v; }
    Mint() { v = 0; }
    Mint(ll _v) {
        v = (-mod < _v && _v < mod) ? _v : _v % mod;
        if (v < 0) v += mod;
    }
    friend bool operator==(const Mint& a, const Mint& b) { return a.v == b.v; }
    friend bool operator!=(const Mint& a, const Mint& b) { return !(a == b); }
    friend bool operator<(const Mint& a, const Mint& b) { return a.v < b.v; }

    Mint& operator+=(const Mint& m) { if ((v += m.v) >= mod) v -= mod; return *this; }
    Mint& operator-=(const Mint& m) { if ((v -= m.v) < 0) v += mod; return *this; }
    Mint& operator*=(const Mint& m) { v = v*m.v%mod; return *this; }
    Mint& operator/=(const Mint& m) { return (*this) *= inv(m); }
    Mint& operator^=(const ll& e) { return (*this) = pow(*this, e); }

    friend Mint pow(Mint a, ll p) {
        Mint ans = 1; assert(p >= 0);
        for (; p; p /= 2, a *= a) if (p & 1) ans *= a;
        return ans;
    }

    friend Mint inv(const Mint& a) { assert(a.v != 0); return pow(a, mod-2); }

    Mint operator-() const { return Mint(-v); }
    Mint& operator++() { return *this += 1; }
    Mint& operator--() { return *this -= 1; }
    Mint operator++(int) { Mint temp; temp.v = v++; return temp; }
    Mint operator--(int) { Mint temp; temp.v = v--; return temp; }

    friend Mint operator+(Mint a, const Mint& b) { return a += b; }
    friend Mint operator-(Mint a, const Mint& b) { return a -= b; }
    friend Mint operator*(Mint a, const Mint& b) { return a *= b; }
    friend Mint operator/(Mint a, const Mint& b) { return a /= b; }
    friend Mint operator^(Mint a, const ll& e) { return a ^= e; }

    friend ostream& operator<<(ostream& os, const Mint& m) {
        os << m.v; return os;
    }

    friend istream& operator>>(istream& is, Mint& m) {
        ll x; is >> x;
        m.v = x;
        return is;
    }
};

struct Trie {

    struct Node {
        vector<int> nxt;
        char ch;
        int end;
        Node(char ch) : ch(ch) {
            end = 0;
            nxt.resize(K, -1);
        }
    };

    vector<Node> nodes;
    int sz;

    Trie() {
        nodes.emplace_back('$');
        sz = 1;
    }

    void insert(string& s) {
        int node = 0;
        for (char c: s) {
            int cc = c - 'a';
            if (nodes[node].nxt[cc] == -1) {
                nodes[node].nxt[cc] = sz++;
                nodes.emplace_back(c);
            }
            node = nodes[node].nxt[cc];
        }
        nodes[node].end++;
    }
};

template<typename T, int N>
struct Matrix {
    T v[N][N];

    Matrix() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                v[i][j] = 0;
            }
        }
    }

    static Matrix<T, N> Identity() {
        Matrix I;
        for (int i = 0; i < N; i++) I.v[i][i] = 1;
        return I;
    }

    Matrix<T, N> operator* (const Matrix<T, N> &oth) const {
        Matrix<T, N> res;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                for (int k = 0; k < N; k++) {
                    res.v[i][j] += v[i][k] * oth.v[k][j];
                }
            }
        }
        return res;
    }

    Matrix<T, N> operator^ (ll x) {
        Matrix<T, N> A = (*this), B = Identity();
        while (x) {
            if (x & 1) B = (B * A);
            A = (A * A);
            x >>= 1;
        }
        return B;
    }
};

void solve() {
    int n, m;
    cin >> n >> m;

    Trie trie;
    for (int i = 0; i < n; i++) {
        string s; cin >> s;
        trie.insert(s);
    }

    int sz = 1;
    vector<vector<int>> trans(sz);
    map<array<int, 2>, int> mp;
    vector<array<int, 2>> states;
    queue<array<int, 2>> q;

    states.push_back({0, 0});
    q.push({0, 0});
    mp[{0, 0}] = 0;

    while (q.size()) {
        int x = q.front()[0], y = q.front()[1]; q.pop();

        for (int i = 0; i < K; i++) {
            vector<int> xadj, yadj;
            if (trie.nodes[x].nxt[i] != -1) {
                xadj.push_back(trie.nodes[x].nxt[i]);
            }
            if (trie.nodes[x].end && trie.nodes[0].nxt[i] != -1) {
                xadj.push_back(trie.nodes[0].nxt[i]);
            }
            if (trie.nodes[y].nxt[i] != -1) {
                yadj.push_back(trie.nodes[y].nxt[i]);
            }
            if (trie.nodes[y].end && trie.nodes[0].nxt[i] != -1) {
                yadj.push_back(trie.nodes[0].nxt[i]);
            }

            for (int xx: xadj) {
                for (int yy: yadj) {
                    if (!mp.count({xx, yy})) {
                        mp[{xx, yy}] = sz++;
                        states.push_back({xx, yy});
                        trans.push_back({});
                        q.push({xx, yy});
                    }
                    trans[mp[{x, y}]].push_back(mp[{xx, yy}]);
                }
            }
        }
    }

    Matrix<Mint, N> mat;

    for (int i = 0; i < sz; i++) {
        for (int j: trans[i]) {
            mat.v[j][i]++;
        }
    }

    auto res = mat ^ m;

    Mint ans = 0;
    for (int i = 0; i < sz; i++) {
        int x = states[i][0], y = states[i][1];
        if (trie.nodes[x].end && trie.nodes[y].end) {
            ans += res.v[i][0];
        }
    }

    cout << ans << "\n";
}

int main() {
    FASTIO;
    PRECISION;

    int t = 1;
    // cin >> t;

    for (int i = 1; i <= t; i++) {
        solve();
    }
}

#include <bits/stdc++.h>
using namespace std;const int mod = 998244353;int n, m;int ch[50][26], ndcnt;int nxt[50], val[50], nc;map<int, int> mp[50];
void ins(string s) {int t = 0;for (auto i: s) {int c = i - 'a';if (!ch[t][c]) ch[t][c] = ++ndcnt;	t = ch[t][c];}++val[t];}
struct mat {
	int a[600][600];

	void output() {
		for (int i = 1; i <= nc; ++i)
			for (int j = 1; j <= nc; ++j)
				printf("%d%c", a[i][j], " \n"[j == nc]);
	}
}v;

void adde(int l, int r, int w) {
	v.a[l][r] += w;
	v.a[l][r] %= mod;
}

mat operator * (const mat &a, const mat &b) {
	mat ans;
	memset(ans.a, 0, sizeof ans.a);
	for (int i = 1; i <= nc; ++i)
		for (int k = 1; k <= nc; ++k)
			for (int j = 1; j <= nc; ++j) {
				ans.a[i][j] += 1ll * a.a[i][k] * b.a[k][j] % mod;
				if (ans.a[i][j] >= mod) ans.a[i][j] -= mod;
			}
	return ans;
}

mat fpow(mat x, int y) {
	mat ans;
	for (int i = 1; i <= nc; ++i)
		for (int j = 1; j <= nc; ++j)
			ans.a[i][j] = i == j;
	while (y) {
		if (y & 1) ans = ans * x;
		y >>= 1; x = x * x;
	}
	return ans;
}

int dfs(int x, int y) {
	if (x > y) swap(x, y);
	int &p = mp[x][y];
	if (p == 0) p = ++nc;
	else return p;
	for (int i = 0; i < 26; ++i)
		if (ch[x][i] && ch[y][i]) {
			int dx = ch[x][i], dy = ch[y][i];
			adde(p, dfs(0, 0), val[dx] * val[dy]);
			adde(p, dfs(dx, 0), val[dy]);
			adde(p, dfs(0, dy), val[dx]);
			adde(p, dfs(dx, dy), 1);
		}
	return p;
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		string s; cin >> s;
		ins(s);
	}
	dfs(0, 0);
	v = fpow(v, m);
	printf("%d", v.a[1][1]);

}

#include<bits/stdc++.h>
#define x first
#define y second
#define bug(x) cerr<<#x<<" = "<<x<<'\n'

using namespace std;

typedef pair <int, int> ii;

const int maxn = 201, mod = 998244353, K = 26;

int mul(int a, int b) {
  return 1ll * a * b % mod;
}

int add(int a, int b) {
  a += b;
  if (a >= mod) a -= mod;
  if (a < 0) a += mod;
  return a;
}

struct mat {
  int R, C;
  int A[maxn][maxn];
  mat(int _R, int _C) {
    R = _R; C = _C;
    for (int i = 0; i < R; ++i) {
      for (int j = 0; j < C; ++j) {
        A[i][j] = 0;
      }
    }
  }
  mat operator * (const mat& other) const {
    assert(C == other.R);
    mat ret = mat(R, other.C);
    for (int i = 0; i < R; ++i) {
      for (int j = 0; j < other.C; ++j) {
        for (int k = 0; k < C; ++k) {
          ret.A[i][j] = add(ret.A[i][j], mul(A[i][k], other.A[k][j]));
        }
      }
    }
    return ret;
  }
  mat power(int e) {
    mat ret(R, C);
    for (int i = 0; i < R; ++i) {
      ret.A[i][i] = 1;
    }
    mat B = *this;
    while (e) {
      if (e & 1) ret = ret * B;
      e >>= 1;
      B = B * B;
    }
    return ret;
  }
};

struct node {
  int nxt[K];
  bool leaf = false;
  node() {
    fill(begin(nxt), end(nxt), -1);
  }
};

vector <node> trie(1);

void add(const string& S) {
  int v = 0;
  for (char ch : S) {
    int c = ch - 'a';
    if (trie[v].nxt[c] == -1) {
      trie[v].nxt[c] = trie.size();
      trie.emplace_back();
    }
    v = trie[v].nxt[c];
  }
  trie[v].leaf = true;
}

int N, M, id[maxn][maxn];
string S[10];
vector <ii> a;
vector <int> G[maxn];

int main() {
  ios::sync_with_stdio(0); cin.tie(0);
//  freopen("cc.inp", "r", stdin);
//  freopen("cc.out", "w", stdout);
  cin >> N >> M;
  for (int i = 0; i < N; ++i) {
    cin >> S[i];
    add(S[i]);
  }
  memset(id, -1, sizeof id);
  id[0][0] = 0;
  a.push_back({0, 0});
  queue <int> Q;
  Q.push(0);
  while (Q.size()) {
    int i = Q.front(); Q.pop();
    int u = a[i].x, v = a[i].y;
    for (int k = 0; k < 26; ++k) {
      vector <int> nu, nv;
      if (trie[u].nxt[k] != -1) nu.push_back(trie[u].nxt[k]);
      if (trie[v].nxt[k] != -1) nv.push_back(trie[v].nxt[k]);
      if (trie[u].leaf && trie[0].nxt[k] != -1) nu.push_back(trie[0].nxt[k]);
      if (trie[v].leaf && trie[0].nxt[k] != -1) nv.push_back(trie[0].nxt[k]);
      for (int p : nu) {
        for (int q : nv) {
         int x = p, y = q;
         if (x > y) swap(x, y);
          if (id[x][y] == -1) {
            id[x][y] = a.size();
            a.push_back({x, y});
            Q.push(id[x][y]);
          }
          G[i].push_back(id[x][y]);
        }
      }
    }
  }
  N = a.size();
  mat A(1, N); A.A[0][0] = 1;
  mat B(N, N);
  for (int i = 0; i < N; ++i) {
    for (int j : G[i]) {
      B.A[i][j]++;
    }
  }
  B = B.power(M);
  A = A * B;
  int ans = 0;
  for (int i = 0; i < (int)a.size(); ++i) {
    auto p = a[i];
    int x = p.x, y = p.y;
    if (trie[x].leaf && trie[y].leaf) {
      ans = add(ans, A.A[0][i]);
    }
  }
  cout << ans << '\n';
}

//12252024832524
#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define TT template<typename T>
using namespace std;

typedef long long LL;
typedef pair<int,int> pii;
const int MAXN = 165;
const int MOD = 998244353;
int N,M;
char c[MAXN];

LL Read()
{
	LL x = 0,f = 1;char c = getchar();
	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

struct Matrix
{
	int n,m;
	int a[MAXN][MAXN];

	Matrix(){memset(a,0,sizeof(a));}

	Matrix operator * (const Matrix &C)const{
		Matrix ret; ret.n = n; ret.m = m;
		for(int i = 0;i < n;++ i)
			for(int k = 0;k < m;++ k)
				if(a[i][k])
					for(int j = 0;j < C.m;++ j)
						ret.a[i][j] = (ret.a[i][j] + 1ll * a[i][k] * C.a[k][j]) % MOD;
		return ret;
	}

	void print()
	{
		printf("%d %d\n",n,m);
		for(int i = 0;i < n;++ i,putchar('\n'))
			for(int j = 0;j < m;++ j)
				Put(a[i][j],' ');
	}
}A;
Matrix Mqpow(Matrix C,int y)
{
	Matrix I; I.n = I.m = C.n;
	for(int i = 0;i < I.n;++ i) I.a[i][i] = 1;
	while(y){if(y & 1) I = I * C;C = C * C;y >>= 1;}
	return I;
}

pii q[MAXN];
int IDtot,h;
map<pii,int> ID;
int GetID(pii x)
{
	if(x.first > x.second) swap(x.first,x.second);
	if(ID.count(x)) return ID[x];
	ID[x] = ++IDtot;
	q[++h] = x;
	return IDtot;
}

int tot;
struct Trie
{
	int ch[26]; bool fk;
}t[MAXN];

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	N = Read(); M = Read();
	for(int i = 1;i <= N;++ i)
	{
		scanf("%s",c);
		int now = 0,len = strlen(c);
		for(int j = 0;j < len;++ j)
		{
			int to = c[j] - 'a';
			if(!t[now].ch[to]) t[now].ch[to] = ++tot;
			now = t[now].ch[to];
		}
		t[now].fk = 1;
	}
	q[++h] = make_pair(0,0); ID[q[h]] = 0;
	while(h >= 1)
	{
		pii x = q[h--];
		int xID = GetID(x);
		for(int i = 0;i < 26;++ i)
		{
			int u = t[x.first].ch[i],v = t[x.second].ch[i];
			if(!u || !v) continue;
			pii to = make_pair(u,v);
			A.a[xID][GetID(to)]++;
			if(t[u].fk) A.a[xID][GetID(make_pair(0,v))]++;
			if(t[v].fk) A.a[xID][GetID(make_pair(u,0))]++;
			if(t[u].fk && t[v].fk) A.a[xID][0]++;
		}
	}
	A.n = A.m = IDtot+1;
//	Mqpow(A,M).print();
	Put(Mqpow(A,M).a[0][0]);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define MAXN 300005
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=0x7f7f7f7f7f7f;
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int qkpow(int a,int s){int t=1;while(s){if(s&1)t=1ll*a*t%mo;a=1ll*a*a%mo;s>>=1;}return t;}
int n,m,idx,len[10],sum,id[10][10];
struct matrix{
	int c[505][505];
	matrix(){memset(c,0,sizeof(c));}
	matrix operator * (const matrix &rhs){
		matrix res;
		for(int i=1;i<=idx;i++)
			for(int k=1;k<=idx;k++)
				if(c[i][k])for(int j=1;j<=idx;j++)
					res.c[i][j]=add(res.c[i][j],1ll*c[i][k]*rhs.c[k][j]%mo);
		return res;
	}
	void print(){
		for(int i=1;i<=idx;i++,puts(""))
			for(int j=1;j<=idx;j++)
				printf("%d ",c[i][j]);
	}
}A,P[35],T;
char str[10][10];
signed main(){
	read(n);read(m);
	for(int i=1;i<=n;i++){
		scanf("%s",str[i]+1);len[i]=(int)strlen(str[i]+1);
		for(int j=2;j<=len[i];j++)id[i][j]=++idx;
	}
	idx++;int nod=idx;//printf("%d\n",nod);
	for(int i=1;i<=n;i++)id[i][1]=nod;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=len[i];j++)
			for(int k=1;k<=n;k++){
				bool fg=0;int lim=min(len[i]-j+1,len[k]);
				for(int l=1;l<=lim;l++)
					if(str[i][j+l-1]!=str[k][l])fg=1;
				if(fg)continue;int las=id[i][j],now;
				for(int l=2;l<=lim;l++){now=++idx;A.c[las][now]++;las=now;}
				if(len[i]-j+1==len[k])A.c[las][nod]++;
				if(len[i]-j+1<len[k])A.c[las][id[k][lim+1]]++;
				if(len[i]-j+1>len[k])A.c[las][id[i][j+lim]]++;
			}
	P[0]=A;for(int i=1;i<30;i++)P[i]=P[i-1]*P[i-1];
	for(int i=1;i<=idx;i++)T.c[i][i]=1;
	for(int i=0;i<30;i++)if(m&(1<<i))T=T*P[i];
	printf("%d\n",T.c[nod][nod]);
	return 0;
}
/*
*/

// Exported by Exporter.exe

// Included from test.cpp
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define F first
#define S second
#define MP make_pair
#define MTP make_tuple
#define R Read
#define RD Read_Digit
#define RP Read_P
#define RL Read_Loop
#define RLD Read_Loop_Digit
#define RLP Read_Loop_P
#ifdef ONLINE_JUDGE
	#define Debug(x) ;
	#define Debugln(x) ;
	#define Debug_Array(n,x) ;
	#define Debugln_Array(n,x) ;
	#define NL ;
#else
	#define Debug(x) printf("%s :", (#x)); _Debug(x)
	#define Debugln(x) printf("%s :", (#x)); _Debugln(x)
	#define Debug_Array(n,x) printf("%s :", (#x)); _Debug_Array((n), (x))
	#define Debugln_Array(n,x) printf("%s :", (#x)); _Debugln_Array((n), (x))
	#define NL printf("\n")
#endif
typedef long long int ll;
typedef unsigned long long int ull;

constexpr int kN = 170;
constexpr int kMod = 998244353;
// constexpr int kMod = int(1E9 + 7);
// constexpr int kInf = 0x3f3f3f3f;
// constexpr ll kInf = 0x3f3f3f3f3f3f3f3f;
// constexpr double kPi = acos(-1);
// constexpr double kEps = 1E-9;

// Included from C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp
// --- Get ---
static inline char Get_Raw_Char() {
	static char buf[1 << 16], *p = buf, *end = buf;
	if (p == end) {
		if ((end = buf + fread(buf, 1, 1 << 16, stdin)) == buf) return '\0';
		p = buf;
	}
	return *p++;
}

// --- Read ---
template <typename T> static inline void Read_P(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	return ;
}

template <typename T> static inline void Read(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	if (neg) n = -n;
	return ;
}

template <typename T> static inline void Read_Digit(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	return ;
}

// --- Read multiple ---
template <typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read(n); return Read(Fargs...);}
template <typename T, typename... Targs> static inline void Read_Digit(T &n, Targs&... Fargs) {Read_Digit(n); return Read_Digit(Fargs...);}
template <typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P(n); return Read_P(Fargs...);}

// --- Read Loop ---
template <typename T> static inline void Read_Loop_i(int i, T *a) {return Read(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_i(int i, T *a, Targs*... Fargs) {Read(a[i]); return Read_Loop_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_Digit_i(int i, T *a) {return Read_Digit(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_Digit_i(int i, T *a, Targs*... Fargs) {Read_Digit(a[i]); return Read_Loop_Digit_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_Digit(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_Digit_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_P_i(int i, T *a) {return Read_P(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_P_i(int i, T *a, Targs*... Fargs) {Read_P(a[i]); return Read_Loop_P_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_P(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_P_i(i, Fargs...);}

// --- Float ---
template <int mul, typename T> static inline void Read(T &n) {
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;

	if (neg) n = -n;
	return ;
}

template <int mul, typename T> static inline void Read_P(T &n) {
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;

	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;
	return ;
}

template <int mul, typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read<mul>(n); return Read<mul>(Fargs...);}
template <int mul, typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P<mul>(n); return Read_P<mul>(Fargs...);}

// --- init ---
inline void IOS() {ios::sync_with_stdio(false); cin.tie(0);}
inline void Freopen(const char *in, const char *out) {freopen(in, "r", stdin); freopen(out, "w", stdout);}

// --- Output ---
template <typename T> void Print(T x) {
	if (x < 0) {
		printf("-");
		x = -x;
	}
	if (x == 0) printf("0");
	else {
		static int val[100];
		int idx = -1;
		while (x) {
			val[++idx] = x % 10;
			x /= 10;
		}
		while (idx >= 0) printf("%d", val[idx--]);
	}
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp
template <typename T> inline void sort(vector<T> &v) {return sort(v.begin(), v.end());}
template <typename T> inline void sort_r(vector<T> &v) {return sort(v.begin(), v.end(), greater<T>());}

template <typename T> inline void reverse(vector<T> &v) {return reverse(v.begin(), v.end());}

template <typename T> inline void Merge(vector<T> &a, vector<T> &b, vector<T> &c) {
	if (c.size() < a.size() + b.size()) c.resize(a.size() + b.size());
	merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
	return ;
}

template <typename T> inline void Discrete(vector<T> &v) {sort(v); v.resize(unique(v.begin(), v.end()) - v.begin());}

template <typename T> using PQ = priority_queue<T>;
template <typename T> using PQ_R = priority_queue<T, vector<T>, greater<T>>;

template <typename T> inline T ABS(T n) {return n >= 0 ? n : -n;}
template <typename T> inline T gcd(T a, T b) {return b ? gcd(b, a % b) : a;}
template <typename T> inline T lcm(T a, T b) {return a * b / gcd(a, b);}
template <typename T, typename... Targs> inline T min(T a, T b, T c, Targs... args) {return min(a, min(b, c, args...));}
template <typename T, typename... Targs> inline T max(T a, T b, T c, Targs... args) {return max(a, max(b, c, args...));}
template <typename T> inline void chmin(T &a, T b) {a = min(a, b); return ;}
template <typename T> inline void chmax(T &a, T b) {a = max(a, b); return ;}
template <typename T, typename... Targs> inline void chmin(T &a, T b, T c, Targs... args) {a = min(a, min(b, c, args...)); return ;}
template <typename T, typename... Targs> inline void chmax(T &a, T b, T c, Targs... args) {a = max(a, max(b, c, args...)); return ;}

template <typename T> inline int Digit_Sum(T a) {
	int ans = 0;
	while (a) {
		ans += a % 10;
		a /= 10;
	}
	return ans;
}
template <typename T> inline int Num_Length(T a) {
	int ans = 1;
	while (a /= 10) ans++;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp
void _print(int x) {printf("%d", x);}
void _print(long long int x) {printf("%lld", x);}
void _print(double x) {printf("%lf", x);}
template <typename T> void _print(T x) {return x.out();}
template <typename T1, typename T2> void _print(pair<T1, T2> x) {printf("("); _print(x.first); printf(", "); _print(x.second); printf(")");}

template <typename T> void _Debug(T x) {_print(x); printf("\n");}
template <typename T> void _Debug(vector<T> v) {
	if (v.empty()) printf(" empty");
	else for (T i : v) printf(" "), _print(i);
	printf("\n");
}

template <typename T1, typename T2, typename T3> void _Debug(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf(" ");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf(" ");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf(" ");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf(" ");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(vector<T> v) {
	if (v.empty()) printf(" empty\n");
	else {
		for (T i : v) printf("\n"), _print(i);
		printf("\n");
	}
}

template <typename T1, typename T2, typename T3> void _Debugln(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf("\n");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf("\n");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf("\n");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf("\n");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debug_Array(int n, const T *x) {for (int i = 1; i <= n; i++) printf(" "), _print(x[i]); printf("\n");}
template <typename T> void _Debugln_Array(int n, const T *x) {printf("\n"); for (int i = 1; i <= n; i++) _print(x[i]), printf("\n");}
// End of C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp
template <typename T1, typename T2> T1 Pow(T1 a, T2 b) {
	T1 ans(1);
	while (b) {
		if (b & 1) ans *= a;
		a *= a;
		b >>= 1;
	}
	return ans;
}

template <int kMod> struct Mod_Int {
	constexpr static int Mod() {return kMod;}

	int val;
	Mod_Int() {val = 0;}
	template <typename T> Mod_Int(const T &x) {val = x;}
	template <int nMod> Mod_Int(const Mod_Int<nMod> &x) {val = x.val;}

	Mod_Int inv() const {return Pow(*this, kMod - 2);}

	Mod_Int operator + (const Mod_Int &x) const {
		Mod_Int ans(val + x.val);
		if (ans.val >= kMod) ans.val -= kMod;
		return ans;
	}
	Mod_Int operator - (const Mod_Int &x) const {
		Mod_Int ans(val - x.val);
		if (ans.val < 0) ans.val += kMod;
		return ans;
	}
	Mod_Int operator * (const Mod_Int &x) const {return Mod_Int(1LL * val * x.val % kMod);}
	Mod_Int operator / (const Mod_Int &x) const {return *this * x.inv();}
	Mod_Int operator ^ (const Mod_Int &x) const {return Pow(*this, x.val);}
	Mod_Int operator << (const int &x) const {return ((1LL * val) << x) % kMod;}

	Mod_Int operator += (const Mod_Int &x) {return *this = *this + x;}
	Mod_Int operator -= (const Mod_Int &x) {return *this = *this - x;}
	Mod_Int operator *= (const Mod_Int &x) {return *this = *this * x;}
	Mod_Int operator /= (const Mod_Int &x) {return *this = *this / x;}
	Mod_Int operator ^= (const Mod_Int &x) {return *this = Pow(*this, x.val);}
	Mod_Int operator <<= (const int &x) {return *this = *this << x;}

	Mod_Int operator ++(int) {
		val++;
		if (val >= kMod) val -= kMod;
		return *this;
	}
	Mod_Int operator --(int) {
		val--;
		if (val < 0) val += kMod;
		return *this;
	}

	bool operator < (const Mod_Int &x) const {return val < x.val;}
	bool operator > (const Mod_Int &x) const {return val > x.val;}
	bool operator <= (const Mod_Int &x) const {return val <= x.val;}
	bool operator >= (const Mod_Int &x) const {return val >= x.val;}
	bool operator == (const Mod_Int &x) const {return val == x.val;}
	bool operator != (const Mod_Int &x) const {return val != x.val;}

	void out() const {printf("%d", val);}
};

using Mint = Mod_Int<kMod>;

namespace Factorial {
	Mint *f, *inf;
	bool preprocessed_factorial;
	void Pre_Factorial(const int &sz) {
		if (preprocessed_factorial) return ;
		preprocessed_factorial = true;
		f = new Mint[sz + 1];
		inf = new Mint[sz + 1];
		f[0] = f[1] = inf[0] = inf[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		inf[sz] = f[sz].inv();
		for (int i = sz; i > 2; i--) inf[i - 1] = inf[i] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] * inf[m];}
	inline Mint C(const int &n, const int &m) {return f[n] * inf[m] * inf[n - m];}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] * inf[m] * inf[n - 1];}
	inline Mint Catalan(const int &n) {return f[n << 1] * inf[n] * inf[n + 1];}
}

namespace Factorial_No_Inf {
	Mint *f;
	void Pre_Factorial(const int &sz) {
		f = new Mint[sz + 1];
		f[0] = f[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] / f[m];}
	inline Mint C(const int &n, const int &m) {return f[n] / (f[m] * f[n - m]);}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] / (f[m] * f[n - 1]);}
	inline Mint Catalan(const int &n) {return f[n << 1] / (f[n] * f[n + 1]);}
}

namespace Inverse {
	using namespace Factorial;
	Mint *inv;
	void Pre_Inverse(const int &sz) {
		inv = new Mint[sz + 1];
		inv[1] = 1;
		Pre_Factorial(sz);
		for (int i = 1; i <= sz; i++) inv[i] = f[i - 1] * inf[i];
		return ;
	}
};
// End of C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix.cpp
template <typename T> struct Matrix {
	T **val;
	int _size;

	Matrix() {val = nullptr;}
	Matrix(int x, T v = 0) {
		_size = x;
		val = new T* [_size];
		for (int i = 0; i < _size; i++) {
			val[i] = new T [_size];
			memset(val[i], 0, sizeof(T) * _size);
			val[i][i] = v;
		}
	}

	void resize(int x) {
		for (int i = 0; i < _size; i++) delete [] val[i];
		delete [] val;
		_size = x;
		val = new T* [_size];
		for (int i = 0; i < _size; i++) {
			val[i] = new T [_size];
			memset(val[i], 0, sizeof(T) * _size);
		}
		return ;
	}
	int size() const {return _size;}

	T* operator [](int x) {return val[x];}
	T* operator [](int x) const {return val[x];}

	Matrix operator + (const Matrix<T> &x) const {
		Matrix<T> ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] + x[i][j];
		return ans;
	}
	Matrix operator - (const Matrix<T> &x) const {
		Matrix<T> ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] - x[i][j];
		return ans;
	}
	Matrix operator * (const T &x) const {
		Matrix<T> ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator * (const Matrix<T> &x) const {
		Matrix<T> ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) for (int k = 0; k < _size; k++)
			ans[i][j] += val[i][k] * x[k][j];
		return ans;
	}
	Matrix operator / (const T &x) const {
		Matrix<T> ans(_size);
		for (int i = 0; i < _size; i++) for (int j = 0; j < _size; j++) ans[i][j] = val[i][j] * x;
		return ans;
	}
	Matrix operator += (const Matrix<T> &x) {return *this = *this + x;}
	Matrix operator -= (const Matrix<T> &x) {return *this = *this - x;}
	Matrix operator *= (const T &x) {return *this = *this * x;}
	Matrix operator *= (const Matrix<T> &x) {return *this = *this * x;}
	Matrix operator /= (const T &x) {return *this = *this / x;}

	void out() const {
		for (int i = 0; i < _size; i++, printf("\n")) for (int j = 0; j < _size; j++) printf("%5d", val[i][j]);
		return ;
	}
};
// End of C:\Users\ianli\Desktop\CP\template\Math\Matrix\Matrix.cpp

template <typename T> Matrix<T> mPow(Matrix<T> A, ll b) {
	Matrix<T> ans(A.size(), Mint(1));
	while (b) {
		if (b & 1) ans *= A;
		A *= A;
		b >>= 1;
	}
	return ans;
}

string s[kN];
int idx[kN][kN][kN];
int len[kN];
Matrix<Mint> A;

int main() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> s[i];

	for (int i = 1; i <= n; i++) len[i] = int(s[i].size());

	constexpr int kLen = 5;

	int cur = 0;
	// idx : lst s, len diff, wait

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 0; k < kLen; k++)
		idx[i][j][k] = cur++;

	for (int i = 0; i < kLen; i++) idx[0][0][i] = cur++;

	A = Matrix<Mint>(cur, Mint(0));

	for (int i = 1; i <= n; i++) A.val[idx[0][0][len[i] - 1]][idx[0][0][0]]++;

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k < kLen; k++)
		A.val[idx[i][j][k - 1]][idx[i][j][k]]++;

	for (int i = 1; i < kLen; i++) A.val[idx[0][0][i - 1]][idx[0][0][i]]++;

	auto match = [&](int x, int idx, int y, int idy, int len) -> bool {
		for (int i = 0; i < len; i++) if (s[x][idx + i] != s[y][idy + i]) return false;
		return true;
	};

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k <= n; k++) {
		int mn = min(j, len[k]);
		if (!match(i, len[i] - j, k, 0, mn)) continue;

		if (len[k] == j) A.val[idx[0][0][j - 1]][idx[i][j][0]]++;
		else if (len[k] < j) A.val[idx[i][j - len[k]][len[k] - 1]][idx[i][j][0]]++;
		else A.val[idx[k][len[k] - j][j - 1]][idx[i][j][0]]++;
	}

	for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) {
		int mn = min(len[i], len[j]);
		if (match(i, 0, j, 0, mn)) {
			if (len[i] < len[j]) A.val[idx[j][len[j] - len[i]][mn - 1]][idx[0][0][0]] += 2;
			else A.val[idx[i][len[i] - len[j]][mn - 1]][idx[0][0][0]] += 2;
		}
	}

	Mint ans = mPow(A, m).val[idx[0][0][0]][idx[0][0][0]];
	printf("%d\n", ans);
}

// End of test.cpp

#include <bits/stdc++.h>
using namespace std;

const int maxn = 250, P = 998244353;
int n, m, V = 1, tot, mp[maxn][maxn], ed[maxn], ch[maxn][26];
struct mat { int a[maxn][maxn]; } A, B;

mat operator * (const mat &A, const mat &B) {
    mat C; memset(C.a, 0, sizeof(C.a));
    for (int i = 1; i <= tot; i++) {
        for (int j = 1; j <= tot; j++) if (A.a[i][j]) {
            for (int k = 1; k <= tot; k++) {
                C.a[i][k] = (C.a[i][k] + 1LL * A.a[i][j] * B.a[j][k]) % P;
            }
        }
    }
    return C;
}

int main() {
    ios::sync_with_stdio(0);
    cin >> n >> m;
    while (n--) {
        string s; cin >> s;
        int cur = 1;
        for (char $ : s) {
            int c = $ - 'a';
            if (!ch[cur][c]) ch[cur][c] = ++V;
            cur = ch[cur][c];
        }
        ed[cur] = 1;
    }
    queue<pair<int, int>> Q;
    Q.emplace(1, 1), mp[1][1] = ++tot;
    while (!Q.empty()) {
        int u = Q.front().first, v = Q.front().second; Q.pop();
        for (int c = 0; c < 26; c++) if (ch[u][c] && ch[v][c]) {
            int x = ch[u][c], y = ch[v][c];
            for (int a : {0, 1}) for (int b : {0, 1}) {
                if (!ed[x] && a || !ed[y] && b) continue;
                int nx = a ? 1 : x, ny = b ? 1 : y;
                if (!mp[nx][ny]) Q.emplace(nx, ny), mp[nx][ny] = ++tot;
                A.a[mp[u][v]][mp[nx][ny]]++;
            }
        }
    }
    B.a[1][1] = 1;
    for (; m; m >>= 1, A = A * A) {
        if (m & 1) B = B * A;
    }
    printf("%d\n", B.a[1][1]);
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int MOD = 998244353;

typedef vector<int> row;
typedef vector<row> matrix;
inline int add(const int &a, const int &b) {
  int c = a + b;
  if (c >= MOD) c -= MOD;
  return c;
}
inline int mult(const int &a, const int &b) {
  return (long long)a * b % MOD;
}
matrix operator*(const matrix &m1, const matrix &m2) {
  int r = m1.size();
  int m = m1.back().size();
  int c = m2.back().size();
  matrix ret(r, row(c, 0));
  for (int i = 0; i < r; i++) {
    for (int k = 0; k < m; k++) {
      for (int j = 0; j < c; j++) {
        ret[i][j] = add(ret[i][j], mult(m1[i][k], m2[k][j]));
      }
    }
  }
  return ret;
}
matrix one(int dim) {
  matrix ret(dim, row(dim, 0));
  for (int i = 0; i < dim; i++) {
    ret[i][i] = 1;
  }
  return ret;
}
matrix operator^(const matrix &m, const int &e) {
  if (e == 0) return one(m.size());
  matrix sqrtm = m ^ (e / 2);
  matrix ret = sqrtm * sqrtm;
  if (e & 1) ret = ret * m;
  return ret;
}

struct Trie {
  int A = 26;
  int N;
  vector<vector<int>> next;
  vector<int> cnt;

  Trie() : N(0) {
    node();
  }

  int node() {
    next.emplace_back(A, -1);
    cnt.emplace_back(0);
    return N++;
  }

  inline int get(char c) {
    return c - 'a';
  }

  inline void insert(string s) {
    int cur = 0;
    for (char c : s) {
      int to = get(c);
      if (next[cur][to] == -1) next[cur][to] = node();
      cur = next[cur][to];
    }
    cnt[cur]++;
  }
};

const int N = 1605;
int id[N][N];
vector<vector<int>> to;
Trie trie;

void dfs(int i, int j) {
  if (i > j) swap(i, j);
  if (~id[i][j]) return;
  id[i][j] = id[j][i] = to.size();
  to.emplace_back();

  for (int c = 0; c < trie.A; c++) {
    int ni = trie.next[i][c];
    int nj = trie.next[j][c];

    if (~ni and ~nj) {
      dfs(ni, nj);
      to[id[i][j]].push_back(id[ni][nj]);
      if (trie.cnt[nj]) {
        dfs(0, ni);
        to[id[i][j]].push_back(id[0][ni]);
      }
      if (trie.cnt[ni]) {
        dfs(0, nj);
        to[id[i][j]].push_back(id[0][nj]);
      }
      if (trie.cnt[ni] and trie.cnt[nj]) {
        dfs(0, 0);
        to[id[i][j]].push_back(id[0][0]);
      }
    }
  }
}

int main() {
  int n, m;
  scanf("%d %d", &n, &m);

  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    trie.insert(s);
  }

  memset(id, -1, sizeof id);
  dfs(0, 0);

  int dim = to.size();
  matrix mat(dim, row(dim, 0));
  for (int i = 0; i < dim; i++) {
    for (int j : to[i]) {
      mat[i][j]++;
    }
  }

  mat = mat ^ m;

  printf("%d\n", mat[0][0]);

  return 0;
}

#include <bits/stdc++.h>

#define ln                 '\n'
#define all(dat)           dat.begin(), dat.end()
#define loop(i, to)        for (int i = 0; i < to; ++i)
#define cont(i, to)        for (int i = 1; i <= to; ++i)
#define circ(i, fm, to)    for (int i = fm; i <= to; ++i)
#define foreach(i, dat)    for (__typeof(dat.begin()) i = dat.begin(); i != dat.end(); ++i)

typedef long long          num;

using namespace std;

template<int mod> struct modulo {
	typedef modulo T;
	int w;
	operator int() const { return w; }

	modulo() {}
	modulo(int w) { this->w = w; fix(); }
	template<class type> modulo(type w) { this->w = w % mod; fix(); }
	void inline fix() { if (w >= mod || w < -mod) w %= mod; if (w < 0) w += mod; }

	inline T  operator -  () const { return mod - w; }
	inline T& operator += (const T &b) { if ((w += b.w) >= mod) w -= mod; return *this; }
	inline T& operator -= (const T &b) { if ((w -= b.w) < 0) w += mod; return *this; }
	inline T& operator *= (const T &b) { w = (unsigned long long) w * b.w % mod; return *this; }
	inline T& operator /= (const T &b) { return *this *= b.inv(); }
	#define make_operation(P)\
	friend inline T operator P (const T &a, const T &b) { return T(a) P##= b; }\
	template<class U> friend inline T operator P (const T &a, const U &b) { return T(a) P##= b; }\
	template<class U> friend inline T operator P (const U &a, const T &b) { return T(a) P##= b; }
	make_operation(+) make_operation(-) make_operation(*) make_operation(/)
	#undef make_operation

	T inline inv() const {
		int a = w, m = mod, u = 0, v = 1, t;
		for (; a != 0; t = m / a, m -= t * a, swap(a, m), u -= t * v, swap(u, v));
		return u;
	}

	friend inline T pow(const T &w, int p) {
		T a = w, r = 1; for (; p > 0; a *= a, p >>= 1) if (p & 1) r *= a; return r;
	}
};
const int mod = 998244353;
typedef modulo<mod> rem;

template<class A> struct matrix {
	typedef matrix T;
	int n, m;
	vector< vector<A> > d;

	matrix() {}
	matrix(int n, int m, int w = 0): n(n), m(m) {
		d.resize(n, vector<A>(m, 0));
		loop (i, min(n, m)) d[i][i] = w;
	}

	inline const vector<A>& operator [] (int id) const { return d[id]; }
	inline vector<A>& operator [] (int id) { return d[id]; }

	void inline set_size(int n, int m) {
		this->n = n, this->m = m;
		d.resize(n);
		loop (i, n) d[i].resize(m, 0);
	}

	inline T& operator *= (const T &b) { return *this = *this * b; }
	friend inline T operator * (const T &a, const T &b) {
		T r(a.n, b.m);
		loop (i, a.n) loop (k, a.m) if (a[i][k]) loop (j, b.m) if (b[k][j]) r[i][j] += a[i][k] * b[k][j];
		return r;
	}

	friend inline T pow(T a, int p) {
		T r(a.n, a.m, 1);
		for (; p; a *= a, p >>= 1) if (p & 1) r *= a;
		return r;
	}
};
typedef matrix<rem> mat;

const int nsz = 8, ndsz = 41, ssz = ndsz * ndsz, alpsz = 26;
int n, m, sz;
rem ans;
string s;
map< pair<int, int>, int> to;
mat T;

struct trie {
	bool ed[ndsz + 5];
	int rt, sz, g[ndsz + 5][alpsz + 5];

	trie() { rt = ++sz; }

	void inline ins(const string &s) {
		int u = rt;
		loop (i, s.size()) {
			int c = s[i] - 'a', &v = g[u][c];
			v || (v = ++sz), u = v;
		}
		ed[u] = 1;
	}
};
trie tr;

void inline get(vector< pair<int, int> > &to, int u) {
	loop (c, alpsz) {
		int v = tr.g[u][c];
		if (v) to.push_back({v, c});
	}
}

void inline init() {
	static pair<int, int> q[ssz + 5];
	int ql = 0, qr = 0;
	for (q[qr++] = {tr.rt, tr.rt}, to[{tr.rt, tr.rt}] = sz++; ql != qr;) {
		int u = q[ql].first, v = q[ql].second, fm = to[{u, v}], w; ++ql;
		vector< pair<int, int> > to_u, to_v;
		get(to_u, u), get(to_v, v);
		if (tr.ed[u]) get(to_u, tr.rt);
		if (tr.ed[v]) get(to_v, tr.rt);
		for (auto p1 : to_u) for (auto p2 : to_v) if (p1.second == p2.second) {
			int w1 = p1.first, w2 = p2.first;
			if (w1 > w2) swap(w1, w2);
			pair<int, int> p(w1, w2);
			int &to = ::to[p];
			if (!to) q[qr++] = p, to = sz++, T.set_size(sz, sz);
			T[fm][to] += 1;
		}
	}
}

void inline solve() {
	mat R = pow(T, m);
	foreach (it, to) {
		int u = it->first.first, v = it->first.second;
		if (tr.ed[u] && tr.ed[v]) ans += R[0][it->second];
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin >> n >> m;
	cont (i, n) cin >> s, tr.ins(s);
	init();
	solve();
	printf("%d\n", ans.w);
}

// Problem: F. Chainword
// Contest: Codeforces - Educational Codeforces Round 107 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1511/problem/F
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define ll long long
#define pb push_back
#define f first
#define s second
#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL)
#define D(x) cerr << #x << " is " << (x) << "\n";
#define ld long double
#define li __int128

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>; ///find_by_order(),order_of_key()
template<int D, typename T>struct vec : public vector<vec<D - 1, T>> {template<typename... Args>vec(int n = 0, Args... args) : vector<vec<D - 1, T>>(n, vec<D - 1, T>(args...)) {}};
template<typename T>struct vec<1, T> : public vector<T> {vec(int n = 0, T val = T()) : vector<T>(n, val) {}};
template<class T1,class T2> ostream& operator<<(ostream& os, const pair<T1,T2>& a) { os << '{' << a.f << ", " << a.s << '}'; return os; }
template<class T> ostream& operator<<(ostream& os, const vector<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const deque<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T,greater<T> >& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T,greater<T> >& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> ostream& operator<<(ostream& os, const map<T1,T2>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> istream& operator>>(istream& is,pair<T1,T2>& a) {is>>a.f>>a.s;return is;}
template<class T> istream& operator>>(istream& is,vector<T>& a) {for(auto &p:a)is>>p;return is;}
int ri(){int x;scanf("%i",&x);return x;}
void rd(int&x){scanf("%i",&x);}
void rd(long long&x){scanf("%lld",&x);}
void rd(double&x){scanf("%lf",&x);}
void rd(long double&x){scanf("%Lf",&x);}
void rd(string&x){cin>>x;}
void rd(char*x){scanf("%s",x);}
template<typename T1,typename T2>void rd(pair<T1,T2>&x){rd(x.first);rd(x.second);}
template<typename T>void rd(vector<T>&x){for(T&p:x)rd(p);}
template<typename C,typename...T>void rd(C&a,T&...args){rd(a);rd(args...);}
//istream& operator>>(istream& is,__int128& a){string s;is>>s;a=0;int i=0;bool neg=false;if(s[0]=='-')neg=true,i++;for(;i<s.size();i++)a=a*10+s[i]-'0';if(neg)a*=-1;return is;}
//ostream& operator<<(ostream& os,__int128 a){bool neg=false;if(a<0)neg=true,a*=-1;ll high=(a/(__int128)1e18);ll low=(a-(__int128)1e18*high);string res;if(neg)res+='-';if(high>0){res+=to_string(high);string temp=to_string(low);res+=string(18-temp.size(),'0');res+=temp;}else res+=to_string(low);os<<res;return os;}

const int mod=998244353;
int add(int a,int b){
    a+=b;
    if(a>=mod)
        a-=mod;
    return a;
}
int sub(int a,int b){
    a-=b;
    if(a<0)
        a+=mod;
    return a;
}
int mul(int a,int b){
    return (long long)a*b%mod;
}
int pwrmod(int x,int k){
    int ans=1;
    for(;k;k>>=1,x=mul(x,x))
        if(k&1)
            ans=mul(ans,x);
    return ans;
}

const int N=41,L=26;
vector<int> nxt[N][L];
bool kr[N];
bool pref(string a,string b){
	if(a.size()<b.size())
		return pref(b,a);
	return a.substr(a.size()-b.size(),b.size())==b;
}
vector<vector<int>> mul(vector<vector<int>> &a,vector<vector<int>> &b){
	int n=a.size(),m=b[0].size(),l=a[0].size();
	assert(a[0].size()==b.size());
	vector<vector<int>> sol(n,vector<int>(m,0));
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			for(int k=0;k<l;k++)
				sol[i][j]=add(sol[i][j],mul(a[i][k],b[k][j]));
	return sol;
}
int main()
{
	int n=ri(),m=ri();
	vector<string> s(n);
	rd(s);
	map<string,int> done;
	int ind=0;
	vector<string> pre;

	done[""]=ind++;pre.pb("");

	for(int i=0;i<n;i++){
		string tr;
		for(int j=0;j<s[i].size();j++){
			tr+=s[i][j];
			if(done.find(tr)==done.end()){
				done[tr]=ind++;
				pre.pb(tr);
			}
			if(j==s[i].size()-1){
				kr[done[tr]]=1;
			}
		}
	}
	for(auto p:done){
		string tr=p.f;
		int i=p.s;
		for(int j=0;j<26;j++){
			char c='a'+j;
			string novi=tr+c,o;
			o+=c;
			if(done.find(novi)!=done.end())
				nxt[i][j].pb(done[novi]);
			if(kr[i]&&done.find(o)!=done.end())
				nxt[i][j].pb(done[o]);
		}
	}
	vector<pair<int,int>> pr;
	map<pair<int,int>,int> koji;
	for(int i=0;i<ind;i++)
		for(int j=0;j<ind;j++)
			if(pref(pre[i],pre[j])){
				pr.pb({i,j});
				koji[{i,j}]=pr.size()-1;
			}
	int L=pr.size();
	vector<vector<int>> mulMat(L,vector<int>(L,0));
	for(int k=0;k<L;k++){
		int i=pr[k].f,j=pr[k].s;
		for(int l=0;l<26;l++){
			for(auto p:nxt[i][l])
				for(auto d:nxt[j][l]){
					if(koji.find({p,d})!=koji.end()){
						int sl=koji[{p,d}];
						mulMat[k][sl]=add(mulMat[k][sl],1);
					}
				}
		}
	}
	vector<vector<int>> begMat(1,vector<int>(L,0));
	begMat[0][0]=1;
	for(;m;m>>=1,mulMat=mul(mulMat,mulMat))
		if(m&1)
			begMat=mul(begMat,mulMat);
	int sol=0;
	for(int k=0;k<L;k++){
		int i=pr[k].f,j=pr[k].s;
		if(kr[i]&&kr[j])
			sol=add(sol,begMat[0][k]);
	}
	printf("%i\n",sol);
	return 0;
}

#include<bits/stdc++.h>
#define N 250
#define mod 998244353
using namespace std;
int cnt=1,typ[N],fa[N],ch[N][27],fuck,id[N*N],ek[N*N],n,m,ed[N];

int check(int x,int y){
	while(x!=1&&y!=1){
		if(typ[x]!=typ[y])return 0;
		x=fa[x],y=fa[y];
	}
	return 1;
}
int qmo(int x){
	return x+((x>>31)&mod);
}
struct mat{
	int a[N][N];
}ans,I,o,fuckljx;
mat operator * (mat A,mat B){
//	cout<<"check "<<endl;
	mat c=fuckljx;
	for(int i=1;i<=fuck;i++){
		for(int j=1;j<=fuck;j++){
			for(int k=1;k<=fuck;k++){
				c.a[i][j]=qmo(c.a[i][j]+1ll*A.a[i][k]*B.a[k][j]%mod-mod);
			}
		}
	}
	return c;
}
mat q(mat x,int y){
//	cout<<"fuck "<<fuck<<' '<<y<<endl;
	mat tmp=I,sum=x;
	while(y){
		if(y&1)tmp=tmp*sum;
		sum=sum*sum;
		y>>=1;
	}
	return tmp;
}
void print_mat(mat A){
	for(int i=1;i<=fuck;i++){
		for(int j=1;j<=fuck;j++){
			cout<<A.a[i][j]<<' ';
		}
		cout<<endl;
	}
}
char c[N];
int main(){
//	cout<<"check"<<endl;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		scanf("%s",c+1);
		int len=strlen(c+1);
		int p=1;
		for(int j=1;j<=len;j++){
			if(!ch[p][c[j]-'a'+1])ch[p][c[j]-'a'+1]=++cnt,fa[cnt]=p,typ[cnt]=c[j]-'a'+1;
			p=ch[p][c[j]-'a'+1];
		}
		ed[p]=1;
	}
	for(int i=1;i<=cnt;i++){
		for(int j=i;j<=cnt;j++){
			if(!check(i,j))continue;
			id[(i-1)*cnt+j]=++fuck;
			ek[fuck]=(i-1)*cnt+j;
//			cout<<"check "<<fuck<<' '<<(i-1)*cnt+j<<endl;
		}
	}
	for(int i=1;i<=fuck;i++){
		int x=(ek[i]-1)/cnt+1,y=(ek[i]-1)%cnt+1;
		for(int w=1;w<=26;w++){
			if(!ch[x][w]||!ch[y][w])continue;
			int nx=ch[x][w],ny=ch[y][w];
			if(nx>ny)swap(nx,ny);
			ans.a[i][id[(nx-1)*cnt+ny]]++;
			if(ed[nx])ans.a[i][id[ny]]++;
			if(ed[ny])ans.a[i][id[nx]]++;
			if(ed[nx]&&ed[ny])ans.a[i][id[1]]++;
		}
	}
//	cout<<"hh"<<endl;
	for(int i=1;i<=fuck;i++)I.a[i][i]=1;
	o.a[1][1]=1;
//	print_mat(o);
//	print_mat(ans);
//	cout<<"check"<<endl;
	printf("%d\n",(o*q(ans,m)).a[1][1]);
}

#include <bits/stdc++.h>

using namespace std;

template<class Fun>
class y_combinator_result {
  Fun fun_;
public:
  template<class T>
  explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {}

  template<class ...Args>
  decltype(auto) operator()(Args &&...args) {
    return fun_(std::ref(*this), std::forward<Args>(args)...);
  }
};

template<class Fun>
decltype(auto) make_fun(Fun &&fun) {
  return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  struct Node {
    char c;
    int cnt;
    vector<Node*> sons;
    Node(char _c = 0, char _cnt = 0): c(_c), cnt(_cnt) {
      sons.clear();
    }
  };
  Node* root = new Node();
  auto insert = make_fun([&](auto insert, Node* cur, const string& s, int depth) -> void {
    if (depth == (int)s.size()) {
      cur->cnt += 1;
      return;
    }
    for (auto son: cur->sons) {
      if (son->c == s[depth]) {
        insert(son, s, depth + 1);
        return;
      }
    }
    cur->sons.push_back(new Node(s[depth], 0));
    insert(cur->sons.back(), s, depth + 1);
  });
  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    insert(root, s, 0);
  }
  map<Node*, string> path;
  auto dfs = make_fun([&](auto dfs, Node* cur) -> void {
    for (auto son: cur->sons) {
      if (cur == root) {
        path[son] = son->c;
      } else {
        path[son] = path[cur] + son->c;
      }
      dfs(son);
    }
  });
  dfs(root);
  vector<pair<Node*, Node*>> states;
  vector<int> skip;
  for (auto t: path) {
    states.push_back(make_pair(t.first, t.first));
    skip.push_back(0);
  }
  for (auto t1: path) {
    string s1 = t1.second;
    for (auto t2: path) {
      string s2 = t2.second;
      if (s1.size() < s2.size()) {
        if (s2.substr((int)s2.size() - (int)s1.size()) == s1) {
          states.push_back(make_pair(t1.first, t2.first));
          skip.push_back(0);
          states.push_back(make_pair(t2.first, t1.first));
          skip.push_back(1);
        }
      }
    }
  }
  int msize = states.size();
  map<pair<Node*, Node*>, int> id;
  for (int i = 0; i < msize; i++) {
    id[states[i]] = i;
  }
  auto getNext = [&](int state) -> vector<int> {
    Node *x, *y;
    if (state == -1) {
      x = root;
      y = root;
    } else {
      x = states[state].first;
      y = states[state].second;
    }
    vector<int> ret;
    auto go = [&](Node* x, Node *y) -> void {
      for (auto son_x: x->sons) {
        for (auto son_y: y->sons) {
          if (!id.count(make_pair(son_x, son_y))) {
            continue;
          }
          ret.push_back(id[make_pair(son_x, son_y)]);
        }
      }
    };
    go(x, y);
    if (x->cnt) {
      go(root, y);
    }
    if (y->cnt) {
      go(x, root);
    }
    if (x->cnt && y->cnt) {
      go(root, root);
    }
    sort(ret.begin(), ret.end());
    ret.erase(unique(ret.begin(), ret.end()), ret.end());
    return ret;
  };
  using Mat = vector<vector<int>>;
  Mat base(msize, vector<int>(1));
  for (auto state: getNext(-1)) {
    base[state][0] = 1;
  }
  Mat Tr(msize, vector<int>(msize));
  for (int i = 0; i < msize; i++) {
    for (auto j: getNext(i)) {
      Tr[j][i] = 1;
    }
  }
  const int MOD = 998244353;
  auto mul = [&](Mat m1, Mat m2) -> Mat {
    int x = m1.size();
    int y = m2[0].size();
    Mat ret(x, vector<int>(y));
    for (int i = 0; i < x; i++) {
      for (int k = 0; k < msize; k++) {
        int r = m1[i][k];
        for (int j = 0; j < y; j++) {
          ret[i][j] = (ret[i][j] + 1LL * r * m2[k][j]) % MOD;
        }
      }
    }
    return ret;
  };
  auto fexp = [&](Mat x, int y) -> Mat {
    Mat ret(msize, vector<int>(msize));
    for (int i = 0; i < msize; i++) {
      ret[i][i] = 1;
    }
    for (int i = 1; i <= y; i <<= 1) {
      if (i & y) {
        ret = mul(ret, x);
      }
      x = mul(x, x);
    }
    return ret;
  };
  Tr = fexp(Tr, m - 1);
  base = mul(Tr, base);
  int ans = 0;
  for (int j = 0; j < msize; j++) {
    Node *x = states[j].first;
    Node *y = states[j].second;
    if (x->cnt && y->cnt) {
      ans = (ans + base[j][0]) % MOD;
    }
  }
  cout << ans << "\n";
  return 0;
}

#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 305
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
	return f * x;
}
const int MOD = 998244353;
const int inv2 = (MOD+1)/2;
int n,m,i,j,s,o,k;
struct mat{
	int n,m;
	int s[205][205];
	mat(){memset(s,0,sizeof(s));n = m = 0;}
}A,B;
mat operator *(mat a,mat b) {
	mat c;c.n = a.n;c.m = b.m;
	for(int i = 1;i <= a.n;i ++) {
		for(int k = 1;k <= a.m;k ++) {
			if(a.s[i][k])
			for(int j = 1;j <= b.m;j ++) {
				(c.s[i][j] += a.s[i][k] *1ll* b.s[k][j] % MOD) %= MOD;
			}
		}
	}return c;
}
mat qkpow(mat a,int b) {
	mat res;res.n = res.m = a.n;
	for(int i = 1;i <= a.n;i ++) res.s[i][i] = 1;
	while(b > 0) {
		if(b & 1) res = res * a;
		a = a * a; b >>= 1;
	}return res;
}
int tre[MAXN][30],en[MAXN];
int cnt = 1;
void addtree(char *s,int n) {
	int p = 1;
	for(int i = 1;i <= n;i ++) {
		if(!tre[p][s[i]-'a'])  tre[p][s[i]-'a'] = ++ cnt;
		p = tre[p][s[i]-'a'];
	}
	en[p] = 1; return ;
}
int mp[50][50];
bool ok[MAXN];
int dfs(int x,int y) {
	if(mp[x][y]) return mp[x][y];
	mp[x][y] = ++ B.n;B.m ++;
	int id = B.n; ok[id] = (en[x] && en[y]);
	for(int i = 0;i < 26;i ++) {
		if(tre[x][i] && tre[y][i]) {
			B.s[id][dfs(tre[x][i],tre[y][i])] = 1;
		}
		if(en[x] && tre[y][i] && tre[1][i]) {
			B.s[id][dfs(tre[1][i],tre[y][i])] = 1;
		}
		if(en[y] && tre[x][i] && tre[1][i]) {
			B.s[id][dfs(tre[x][i],tre[1][i])] = 1;
		}
		if(en[x] && en[y] && tre[1][i]) {
			B.s[id][dfs(tre[1][i],tre[1][i])] = 1;
		}
	}
	return id;
}
char ss[50];
int main() {
	n = read();m = read();
	for(int i = 1;i <= n;i ++) {
		scanf("%s",ss + 1);
		k = strlen(ss + 1);
		addtree(ss,k);
	}
	dfs(1,1);
	A.n = 1; A.m = B.n;
	A.s[1][1] = 1;
	A = A * qkpow(B,m);
	int ans = 0;
	for(int i = 1;i <= B.n;i ++) {
		if(ok[i]) (ans += A.s[1][i]) %= MOD;
	}
	printf("%d\n",ans);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

template<class Fun>
class y_combinator_result {
  Fun fun_;
public:
  template<class T>
  explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {}

  template<class ...Args>
  decltype(auto) operator()(Args &&...args) {
    return fun_(std::ref(*this), std::forward<Args>(args)...);
  }
};

template<class Fun>
decltype(auto) make_fun(Fun &&fun) {
  return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  struct Node {
    char c;
    int cnt;
    vector<Node*> sons;
    Node(char _c = 0, char _cnt = 0): c(_c), cnt(_cnt) {
      sons.clear();
    }
  };
  Node* root = new Node();
  auto insert = make_fun([&](auto insert, Node* cur, const string& s, int depth) -> void {
    if (depth == (int)s.size()) {
      cur->cnt += 1;
      return;
    }
    for (auto son: cur->sons) {
      if (son->c == s[depth]) {
        insert(son, s, depth + 1);
        return;
      }
    }
    cur->sons.push_back(new Node(s[depth], 0));
    insert(cur->sons.back(), s, depth + 1);
  });
  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    insert(root, s, 0);
  }
  map<Node*, string> path;
  auto dfs = make_fun([&](auto dfs, Node* cur) -> void {
    for (auto son: cur->sons) {
      if (cur == root) {
        path[son] = son->c;
      } else {
        path[son] = path[cur] + son->c;
      }
      dfs(son);
    }
  });
  dfs(root);
  vector<pair<Node*, Node*>> states;
  for (auto t: path) {
    states.push_back(make_pair(t.first, t.first));
  }
  for (auto t1: path) {
    string s1 = t1.second;
    for (auto t2: path) {
      string s2 = t2.second;
      if (s1.size() < s2.size()) {
        if (s2.substr((int)s2.size() - (int)s1.size()) == s1) {
          states.push_back(make_pair(t1.first, t2.first));
          states.push_back(make_pair(t2.first, t1.first));
        }
      }
    }
  }
  int msize = states.size();
  assert(msize <= 300);
  // cout << msize << endl;
  map<pair<Node*, Node*>, int> id;
  for (int i = 0; i < msize; i++) {
    id[states[i]] = i;
  }
  auto getNext = [&](int state) -> vector<int> {
    Node *x, *y;
    if (state == -1) {
      x = root;
      y = root;
    } else {
      x = states[state].first;
      y = states[state].second;
    }
    vector<int> ret;
    auto go = [&](Node* x, Node *y) -> void {
      for (auto son_x: x->sons) {
        for (auto son_y: y->sons) {
          if (!id.count(make_pair(son_x, son_y))) {
            continue;
          }
          ret.push_back(id[make_pair(son_x, son_y)]);
        }
      }
    };
    go(x, y);
    if (x->cnt) {
      go(root, y);
    }
    if (y->cnt) {
      go(x, root);
    }
    if (x->cnt && y->cnt) {
      go(root, root);
    }
    sort(ret.begin(), ret.end());
    ret.erase(unique(ret.begin(), ret.end()), ret.end());
    return ret;
  };
  using Mat = vector<vector<int>>;
  Mat base(msize, vector<int>(1));
  for (auto state: getNext(-1)) {
    base[state][0] = 1;
  }
  Mat Tr(msize, vector<int>(msize));
  for (int i = 0; i < msize; i++) {
    for (auto j: getNext(i)) {
      Tr[j][i] = 1;
    }
  }
  const int MOD = 998244353;
  auto mul = [&](const Mat& m1, const Mat& m2) -> Mat {
    int x = m1.size();
    int y = m2[0].size();
    assert(m1[0].size() == m2.size());
    assert((int)m1[0].size() == msize);
    Mat ret(x, vector<int>(y));
    for (int k = 0; k < msize; k++) {
      for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
          ret[i][j] = (ret[i][j] + 1LL * m1[i][k] * m2[k][j]) % MOD;
        }
      }
    }
    return ret;
  };
  auto fexp = [&](Mat x, int y) -> Mat {
    Mat ret(msize, vector<int>(msize));
    for (int i = 0; i < msize; i++) {
      ret[i][i] = 1;
    }
    for (int i = 1; i <= y; i <<= 1) {
      if (i & y) {
        ret = mul(ret, x);
      }
      x = mul(x, x);
    }
    return ret;
  };
  Tr = fexp(Tr, m - 1);
  base = mul(Tr, base);
  int ans = 0;
  for (int j = 0; j < msize; j++) {
    Node *x = states[j].first;
    Node *y = states[j].second;
    if (x->cnt && y->cnt) {
      ans = (ans + base[j][0]) % MOD;
    }
  }
  cout << ans << "\n";
  return 0;
}

#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
#include "/debug.h"
#else
#define db(...)
#endif

#define all(v) v.begin(), v.end()
#define pb push_back
using ll = long long;
const int NAX = 2e5 + 5, MOD = 998244353;

const int kmod = MOD;

int mul(int a, int b, int mod = kmod)
{
    return (long long)a * b % mod;
}

int add(int a, int b, int mod = kmod)
{
    a += b;
    if (a >= mod)
        a -= mod;
    return a;
}

int sub(int a, int b, int mod = kmod)
{
    a -= b;
    if (a < 0)
        a += mod;
    return a;
}

int power(int base, int index, int mod = kmod)
{
    if (index == 0)
        return 1;
    int temp = power(base, index / 2, mod);
    temp = mul(temp, temp, mod);
    if (index & 1)
        temp = mul(temp, base, mod);
    return temp;
}

int mod_inv(int x, int mod = kmod)
{
    return power(x, mod - 2, mod);
}

// const int _n = 2e5 + 10;
// vector<int> Fact(_n), Inv(_n);

// void pre()
// {
//     Fact[0] = 1;
//     for (int i = 1; i < _n; ++i)
//         Fact[i] = mul(Fact[i - 1], i);
//     Inv[_n - 1] = mod_inv(Fact[_n - 1]);
//     for (int i = _n - 2; i >= 0; --i)
//         Inv[i] = mul(Inv[i + 1], (1 + i));
// }

// int ncr(int n, int r)
// {
//     if (n < 0 || r < 0 || n - r < 0)
//         return 0;
//     return mul(Fact[n], mul(Inv[r], Inv[n - r]));
// }

// int npr(int n, int r)
// {
//     if (n < 0 || r < 0 || n - r < 0)
//         return 0;
//     return mul(Fact[n], Inv[n - r]);
// }

struct matrix
{
    vector<vector<long long>> MAT;
    matrix() {}
    matrix(long long n, long long m)
    {
        MAT.resize(n, vector<long long>(m));
    }
};

matrix mul(const matrix &A, const matrix &B)
{
    int n = A.MAT.size(), m = B.MAT.size(), k = B.MAT[0].size();
    matrix X(n, k);
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < k; ++j)
        {
            X.MAT[i][j] = 0;
            for (int k = 0; k < m; ++k)
                X.MAT[i][j] = add(X.MAT[i][j], mul(A.MAT[i][k], B.MAT[k][j]));
        }
    return X;
}

matrix unit(int n)
{
    matrix X(n, n);
    for (int i = 0; i < n; ++i)
        X.MAT[i][i] = 1;
    return X;
}

matrix power(const matrix &A, long long index)
{
    matrix temp;
    if (index == 0)
        return unit(A.MAT.size());
    temp = power(A, index / 2);
    temp = mul(temp, temp);
    if (index & 1)
        return mul(temp, A);
    return temp;
}

const int AL = 26;

struct node
{
    int nxt[AL];
    bool term;
    node()
    {
        memset(nxt, -1, sizeof(nxt));
        term = false;
    };
    int &operator[](const int x)
    {
        return nxt[x];
    }
};

vector<node> trie = vector<node>(1, node());

void add(const string &s)
{
    int cur = 0;
    int d = 1;
    for (const char &c : s)
    {
        ++d;
        if (trie[cur][c - 'a'] == -1)
        {
            trie[cur][c - 'a'] = trie.size();
            trie.push_back(node());
        }
        cur = trie[cur][c - 'a'];
    }
    trie[cur].term = true;
}

map<pair<int, int>, int> num;
queue<pair<int, int>> q;

int get(int u, int v)
{
    if (u > v)
        swap(u, v);
    if (num.find({u, v}) == num.end())
    {
        int k = num.size();
        num[{u, v}] = k;
        q.push({u, v});
    }
    return num[{u, v}];
}

void solveCase()
{
    int n, m;
    cin >> n >> m;
    for (size_t i = 0; i < n; i++)
    {
        string s;
        cin >> s;
        add(s);
    }
    q.push({0, 0});
    num[{0, 0}] = 0;
    matrix init(170, 170);
    while (!q.empty())
    {
        auto top = q.front();
        q.pop();
        int x = num[top];
        db(top, x);
        for (int i = 0; i < AL; i++)
        {
            int tov = trie[top.first][i];
            int tou = trie[top.second][i];
            if (tov == -1 || tou == -1)
                continue;
            init.MAT[x][get(tov, tou)]++;
            if (trie[tov].term)
                init.MAT[x][get(0, tou)]++;
            if (trie[tou].term)
                init.MAT[x][get(tov, 0)]++;
            if (trie[tov].term && trie[tou].term)
                init.MAT[x][get(0, 0)]++;
        }
    }
    init = power(init, m);
    cout << init.MAT[0][0] << '\n';
}

int32_t main()
{
#ifndef LOCAL
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif
    int t = 1;
    // cin >> t;
    for (int i = 1; i <= t; ++i)
        solveCase();
    return 0;
}

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair <int,int> Pii;
#define reg register
#define mp make_pair
#define pb push_back
#define Mod1(x) ((x>=P)&&(x-=P))
#define Mod2(x) ((x<0)&&(x+=P))
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }

char IO;
template <class T=int> T rd(){
	T s=0; int f=0;
	while(!isdigit(IO=getchar())) f|=IO=='-';
	do s=(s<<1)+(s<<3)+(IO^'0');
	while(isdigit(IO=getchar()));
	return f?-s:s;
}

const int N=250,P=998244353;

int n,m;
char s[N];
int nxt[N][26],cnt,End[N];
string str[N];

int mk[N];
int stx[N],sty[N],stcnt;
int id[N][N];
struct Mat{
	int a[N][N];
	void clear(){ rep(i,1,stcnt) rep(j,1,stcnt) a[i][j]=0; }
	Mat operator * (const Mat x) const {
		Mat res; res.clear();
		rep(i,1,stcnt) rep(j,1,stcnt) if(a[i][j]) rep(k,1,stcnt) res.a[i][k]=(res.a[i][k]+1ll*a[i][j]*x.a[j][k])%P;
		return res;
	}
} x;

Mat qpow(Mat x,int k){
	Mat res=x;
	for(k--;k;k>>=1,x=x*x) if(k&1) res=res*x;
	return res;
}

int main(){
	n=rd(),m=rd();
	rep(i,1,n) {
		scanf("%s",s+1);
		int u=0;
		for(int j=1;s[j];++j) {
			int &v=nxt[u][s[j]-'a'];
			if(!v) v=++cnt,str[v]=str[u]+s[j];
			u=v;
		}
		End[u]=1;
	}
	rep(i,0,cnt) rep(j,0,25) mk[i]|=nxt[i][j];
	rep(u,0,cnt) {
		rep(j,0,str[u].size()) {
			int v=0;
			rep(k,j,str[u].size()-1) {
				v=nxt[v][str[u][k]-'a'];
				if(!v) {
					v=-1;
					break;
				}
			}
			if(~v && mk[u] && mk[v]) {
				//cout<<"new state "<<u<<' '<<v<<' '<<str[u]<<' '<<str[v]<<endl;
				stx[++stcnt]=u,sty[stcnt]=v;
				id[u][v]=stcnt;
			}
		}
	}
	rep(i,1,stcnt) {
		rep(k,0,25) if(nxt[stx[i]][k] && nxt[sty[i]][k]) {
			int a=nxt[stx[i]][k],b=nxt[sty[i]][k];
			rep(x,1-End[a],1) rep(y,1-End[b],1) {
				int u=a*x,v=y*b;
				if(str[u].size()<str[v].size()) swap(u,v);
				if(!id[u][v]) continue;
				//assert(id[u][v]);
				//cout<<"$"<<i<<' '<<k<<' '<<id[u][v]<<endl;
				::x.a[i][id[u][v]]++;
			}
		}
	}
	/*rep(i,1,m) {
		Mat t=qpow(x,m);
		rep(j,1,stcnt) cout<<t.a[1][j]<<' ';
		puts("");
	}*/
	printf("%d\n",qpow(x,m).a[1][1]);
}

#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define pb push_back
//#define int long long
const int MAX=3e5+3,M=200,inf=1e9,mod=998244353 ;
using ii = pair < int , int > ;
void maxx(int &a,int b){if(b>a) a=b;}
struct MT{
    int c[M][M];
};

int N=200;
MT res;
MT operator * (const MT &A,const MT &B){
    for(int i=0;i<=N;i++){
        for(int j=0;j<=N;j++){
            res.c[i][j]=0;
            for(int k=0;k<=N;k++)
                res.c[i][j]=(1LL*A.c[i][k]*B.c[k][j]+res.c[i][j])%mod;
        }
    }
    return res;
}
MT luythua(MT &B,int n){
    MT D=B;
    for(int i=log2(n)-1;i>=0;i--)if(n&(1<<i))
        D=D*D*B;
    else D=D*D;
    return D;
}
int mem[M][M];
string s[8];
int node;
int nex[M][26];
bool en[M];
MT A,B;
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //freopen("F.inp","r",stdin);
    int n,m;
    //A=A*B;
    //return 0;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        cin>>s[i];
        int t=0;
        for(int j=0,c;j<s[i].size();j++){
            c=s[i][j]-'a';
            if(!nex[t][c]) nex[t][c]=++node;
            t=nex[t][c];
        }
        en[t]=1;
    }

    A.c[0][0]=1;

    int cn=0;
    queue < ii > Q;
    Q.push(ii(0,0));

    while(!Q.empty()){
        ii p = Q.front();Q.pop();
        //cout<<p.X<<' '<<p.Y<<'\n';
        int z=mem[p.X][p.Y];
        for(int i=0,x,y;i<26;i++){
            x=nex[p.X][i];y=nex[p.Y][i];
            if(x && y){
                if(x>y) swap(x,y);
                if(!mem[x][y]){
                    mem[x][y]=++cn;
                    Q.push(ii(x,y));
                }
                B.c[z][mem[x][y]]++;
                if(en[x]){
                    if(!mem[0][y]){
                        mem[0][y]=++cn;
                        Q.push(ii(0,y));
                    }
                    B.c[z][mem[0][y]]++;
                    if(en[y]){
                        /*if(!mem[0][0]){
                            mem[0][0]=++cn;
                            Q.push(ii(0,0));
                        }*/
                        B.c[z][0]++;
                    }
                }
                if(en[y]){
                    if(!mem[0][x]){
                        mem[0][x]=++cn;
                        Q.push(ii(0,x));
                    }
                    B.c[z][mem[0][x]]++;
                }
            }
        }

    }
    //cout<<cn;return 0;
    N=cn;
    //B=;
    A=A*luythua(B,m);
    cout<<A.c[0][0]<<'\n';
}

#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define int long long
#define gmax(x,y) x=max(x,y)
#define gmin(x,y) x=min(x,y)
#define F first
#define S second
#define P pair
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a,b) for(int i=a;i<b;i++)
#define V vector
#define RE return
#define ALL(a) a.begin(),a.end()
#define MP make_pair
#define PB emplace_back
#define PF emplace_front
#define FILL(a,b) memset(a,b,sizeof(a))
#define lwb lower_bound
#define upb upper_bound
#define lc (x<<1)
#define rc ((x<<1)|1)
using namespace std;
int it[9][6];
int t[505][505],mod=998244353;
int f[54][54];
struct matrix{
	int s[505][505],n,m;
	void mul(matrix a){
		FOR(i,1,n){
			FOR(j,1,m){
				FOR(k,1,m){
					t[i][j]=(s[i][k]*a.s[k][j]+t[i][j])%mod;
				}
			}
		}
		FOR(i,1,n)FOR(j,1,m)s[i][j]=t[i][j],t[i][j]=0;
	}
}tx,T;
int m,n,l[9];
char c[9][6];
P<int,int> p[54];
bool check(P<int,int> x,P<int,int> y){
	for(int i=x.S,j=y.S;i<=l[x.F]&&j<=l[y.F];i++,j++){
		if(c[x.F][i]!=c[y.F][j])RE 0;
	}
	RE 1;
}
int k;
int nxt(int i){
	P<int,int> tp=p[i];
	tp.S++;
	if(tp.S==l[tp.F]){
		RE k;
	}else RE it[tp.F][tp.S];
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>m;
	int cnt=0;
	FOR(i,1,n){
		string s;
		cin>>s;
		l[i]=s.size();
		FOR(j,1,l[i])c[i][j]=s[j-1];
		rep(j,1,l[i])it[i][j]=++cnt,p[cnt]=MP(i,j);
	}
	it[0][0]=++cnt;p[cnt]=MP(0,0);
	k=cnt;
	cnt=0;
	FOR(i,1,k){
		FOR(j,i,k){
			if(i==k||j==k||check(p[i],p[j]))f[i][j]=f[j][i]=++cnt;
		}
	}
	rep(i,1,k){
		rep(j,i,k){
			if(f[i][j])tx.s[f[i][j]][f[nxt(i)][nxt(j)]]++;
		}
	}
	tx.n=cnt;
	tx.m=cnt;
	rep(i,1,k){
		FOR(j,1,n){
			if(f[nxt(i)][it[j][1]?it[j][1]:k]&&c[j][1]==c[p[i].F][p[i].S+1]){
				tx.s[f[i][k]][f[nxt(i)][it[j][1]?it[j][1]:k]]++;
			}
		}
	}
	FOR(i,1,n){//qaq
		FOR(j,1,n){
			if(c[i][1]==c[j][1]&&f[it[i][1]?it[i][1]:k][it[j][1]?it[j][1]:k]){
				tx.s[f[k][k]][f[it[i][1]?it[i][1]:k][it[j][1]?it[j][1]:k]]++;
			}
		}
	}
	T.n=1;
	T.m=cnt;
	T.s[1][f[k][k]]=1;
	while(m){
		if(m&1)T.mul(tx);
		tx.mul(tx);
		m/=2;
	}
	cout<<T.s[1][f[k][k]];
	RE 0;
}

#include<bits/stdc++.h>
using namespace std;
#ifdef local
void debug_out() { cerr << endl; }
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
    cerr << " " << to_string(H);
    debug_out(T...);
}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
typedef long long ll;
#define f(i, l, r) for(int i=l;i<=r;i++)
#define rf(i, r, l) for(int i=r;i>=l;--i)
#define all(x) x.begin(),x.end()
const int N = 2e5+10, mod = 998244353;
ll power(ll a, ll b) {ll res = 1;while (b) {if (b & 1)res = res * a % mod;a = a * a % mod;b >>= 1;}return res;}
ll INV(ll a){return power(a,mod-2);}
mt19937 Rand(123456);
int Range(int l,int r){
    return l+Rand()%(r-l+1);
}

namespace linear_seq {
#define rep(i,a,n) for (int i=a;i<n;i++)
#define VI vector<int>
#define SZ(x) ((int)(x).size())
#define pb push_back
    const int N = 10010;
    ll res[N], base[N], _c[N], _md[N];
    vector<ll> Md;
    void mul(ll* a, ll* b, int k)
    {
        rep(i, 0, k + k) _c[i] = 0;
        rep(i, 0, k) if (a[i]) rep(j, 0, k) _c[i + j] = (_c[i + j] + a[i] * b[j]) % mod;
        for (int i = k + k - 1; i >= k; i--) if (_c[i])
                rep(j, 0, SZ(Md)) _c[i - k + Md[j]] = (_c[i - k + Md[j]] - _c[i] * _md[Md[j]]) % mod;
        rep(i, 0, k) a[i] = _c[i];
    }
    int solve(ll n, VI a, VI b)
    {
        ll ans = 0, pnt = 0;
        int k = SZ(a);
        assert(SZ(a) == SZ(b));
        rep(i, 0, k) _md[k - 1 - i] = -a[i]; _md[k] = 1;
        Md.clear();
        rep(i, 0, k) if (_md[i] != 0) Md.push_back(i);
        rep(i, 0, k) res[i] = base[i] = 0;
        res[0] = 1;
        while ((1ll << pnt) <= n) pnt++;
        for (int p = pnt; p >= 0; p--)
        {
            mul(res, res, k);
            if ((n >> p) & 1)
            {
                for (int i = k - 1; i >= 0; i--) res[i + 1] = res[i]; res[0] = 0;
                rep(j, 0, SZ(Md)) res[Md[j]] = (res[Md[j]] - res[k] * _md[Md[j]]) % mod;
            }
        }
        rep(i, 0, k) ans = (ans + res[i] * b[i]) % mod;
        if (ans < 0) ans += mod;
        return ans;
    }
    VI BM(VI s) {
        VI C(1, 1), B(1, 1);
        int L = 0, m = 1, b = 1;
        rep(n, 0, SZ(s)) {
            ll d = 0;
            rep(i, 0, L + 1) d = (d + (ll)C[i] * s[n - i]) % mod;
            if (d == 0) ++m;
            else if (2 * L <= n) {
                VI T = C;
                ll c = mod - d * power(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                L = n + 1 - L; B = T; b = d; m = 1;
            }
            else {
                ll c = mod - d * power(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                ++m;
            }
        }
        return C;
    }
    int gao(VI a, ll n) {
        VI c = BM(a);
        c.erase(c.begin());
        debug(c.size());
        rep(i, 0, SZ(c)) c[i] = (mod - c[i]) % mod;
        return solve(n, c, VI(a.begin(), a.begin() + SZ(c)));
    }
};
int dp[510][1700];
vector<int> mat[1700];
struct Trie {
    int tr[N][26], tot;
    bool key[N];
    void insert(char* s) {
        int u = 0;
        for (int i = 1; s[i];i++) {
            int c = s[i] - 'a';
            if (tr[u][c] == 0)tr[u][c] = ++tot;
            u = tr[u][c];
        }
        key[u]=1;
    }
    int id(int x,int y){
        return y+x*(tot+1);
    }
    void build_mat(int m){
        f(u,0,tot)f(v,0,tot)f(w,0,25){
            if(tr[u][w]&&tr[v][w])mat[id(tr[u][w],tr[v][w])].push_back(id(u,v));
            if(tr[0][w]&&tr[v][w]&&key[u])mat[id(tr[0][w],tr[v][w])].push_back(id(u,v));
            if(tr[0][w]&&tr[u][w]&&key[v])mat[id(tr[u][w],tr[0][w])].push_back(id(u,v));
            if(tr[0][w]&&key[v]&&key[u])mat[id(tr[0][w],tr[0][w])].push_back(id(u,v));
        }
        int k=(tot+1)*(tot+1);

        vector<int> res,valid_id;
        f(i,0,tot)f(j,0,tot)if(key[i]&&key[j])valid_id.push_back(id(i,j));
        dp[0][0]=1;
        f(i,1,500) {
            f(j, 0, k)for(auto x:mat[j])dp[i][j] = (dp[i][j] + (ll) dp[i - 1][x]) % mod;
            ll ans=0;
            for(auto I:valid_id)ans+=dp[i][I];
            res.push_back(ans%mod);
        }
        printf("%lld\n", linear_seq::gao(res, m - 1) % mod);
    }
}T;
char s[N];
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef local
    freopen("../in.txt", "r", stdin);
    clock_t beg=clock();
#endif
    int n,m;cin>>n>>m;
    f(i,1,n){
        cin>>s+1;
        T.insert(s);
    }
    T.build_mat(m);
    debug(clock()-beg);
}

#include <bits/stdc++.h>

#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

using namespace std;

typedef long long ll;

const int N = 305;
const int MOD = 998244353;

string pat[69];
vector <pair <ll, int>> trans[N][N];
int n, m, trie[6969][26], ptr = 1, who[6969], L;
ll base[N][N], ret[N][N], temp[N][N], dp[10][10][10], aux[N][N];

void copy (ll a[N][N], ll b[N][N]) {
  for (int i = 0; i < L; ++i) {
    for (int j = 0; j < L; ++j) {
      b[i][j] = a[i][j], a[i][j] = 0;
    }
  }
}

void mult (ll a[N][N], ll b[N][N], ll c[N][N]) {
  for (int k = 0; k < L; ++k) {
    for (int i = 0; i < L; ++i) {
      ll yo = a[i][k];
      for (int j = 0; j < L; ++j) {
        c[i][j] = (c[i][j] + yo * b[k][j]) % MOD;
      }
    }
  }
}

void insert (int idx, string s) {
  int u = 0;
  for (int i = 0; i < s.size(); ++i) {
    int &to = trie[u][s[i] - 'a'];
    if (to == -1) to = ptr++; u = to;
  }
  who[u] = idx;
}

int main() {
  memset(who, -1, sizeof who);
  memset(trie, -1, sizeof trie);
  cin >> n >> m;
  for (int i = 0; i < n; ++i) {
    cin >> pat[i];
    insert(i, pat[i]);
  }
  for (int i = 0; i < n; ++i) {
    for (int r = 0; r < pat[i].size(); ++r) {
      dp[i][r + 1][r] = 1;
      for (int l = r; l >= 0; --l) {
        int at = 0;
        for (int k = l; k <= r; ++k) {
          int to = trie[at][pat[i][k] - 'a'];
          if (to == -1) break; at = to;
          if (who[at] != -1) {
            dp[i][l][r] += dp[i][k + 1][r];
            dp[i][l][r] %= MOD;
          }
        }
      }
    }
  }
  for (int node = 0; node < ptr; ++node) {
    for (int idx = 0; idx < n; ++idx) {
      string s = pat[idx];
      int at = node;
      for (int i = 0; i < s.size(); ++i) {
        int to = trie[at][s[i] - 'a'];
        at = to; if (to == -1) break;
        if (who[at] == -1) continue;
        for (int j = i; j < s.size(); ++j) {
          ll tot = dp[idx][i + 1][j];
          int new_node = 0;
          for (int k = j + 1; k < s.size(); ++k) {
            int yo = trie[new_node][s[k] - 'a'];
            new_node = yo; if (yo == -1) break;
          }
          if (new_node == -1) continue;
          trans[node][idx].emplace_back(tot, new_node);
        }
      }
      if (at == -1) continue;
      trans[node][idx].emplace_back(1, at);
    }
  }
  L = 5 * ptr;
  for (int node = 0; node < ptr; ++node) {
    for (int idx = 0; idx < n; ++idx) {
      int len = pat[idx].size();
      for (auto &[tot, new_node] : trans[node][idx]) {
        int yo = (len - 1) * ptr + new_node;
        base[node][yo] += tot, base[node][yo] %= MOD;
      }
    }
  }
  for (int node = ptr, i = 0; node < L; ++node, ++i) {
    base[node][i] = 1;
  }
  // for (int i = 0; i < L; ++i) {
  //   for (int j = 0; j < L; ++j) cerr << base[i][j] << " ";
  //   cerr << '\n';
  // }
  for (int i = 0; i < L; ++i) ret[i][i] = 1;
  while (m) {
    if (m & 1) mult(ret, base, temp), copy(temp, ret);
    mult(base, base, temp), copy(temp, base), m >>= 1;
  }
  aux[0][0] = 1;
  for (int i = 1; i < 5; ++i) {
    for (int j = 0; j < ptr; ++j) {
      for (int idx = 0; idx < n; ++idx) {
        int len = pat[idx].size();
        if (len > i) continue;
        for (auto &[tot, new_node] : trans[j][idx]) {
          aux[i][j] += tot * aux[i - len][new_node];
          aux[i][j] %= MOD;
        }
      }
    }
  }
  vector <ll> vec(L);
  for (int i = 4, at = 0; i >= 0; --i) {
    for (int j = 0; j < ptr; ++j, ++at) vec[at] = aux[i][j];
  }
  ll ans = 0;
  for (int i = 0; i < L; ++i) {
    ans += ret[4 * ptr][i] * vec[i], ans %= MOD;
  }
  cout << ans << '\n';
  return 0;
}

#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")

#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}

#define fi first
#define se second
#define pb push_back
#define mkp make_pair
typedef pair<int,int>pii;
typedef vector<int>vi;

#define mod 998244353
struct modint{
    int x;
    modint(int o=0){x=o;}
    modint &operator = (int o){return x=o,*this;}
    modint &operator +=(modint o){return x=x+o.x>=mod?x+o.x-mod:x+o.x,*this;}
    modint &operator -=(modint o){return x=x-o.x<0?x-o.x+mod:x-o.x,*this;}
    modint &operator *=(modint o){return x=1ll*x*o.x%mod,*this;}
    modint &operator ^=(int b){
        modint a=*this,c=1;
        for(;b;b>>=1,a*=a)if(b&1)c*=a;
        return x=c.x,*this;
    }
    modint &operator /=(modint o){return *this *=o^=mod-2;}
    modint &operator +=(int o){return x=x+o>=mod?x+o-mod:x+o,*this;}
    modint &operator -=(int o){return x=x-o<0?x-o+mod:x-o,*this;}
    modint &operator *=(int o){return x=1ll*x*o%mod,*this;}
    modint &operator /=(int o){return *this *= ((modint(o))^=mod-2);}
    template<class I>friend modint operator +(modint a,I b){return a+=b;}
    template<class I>friend modint operator -(modint a,I b){return a-=b;}
    template<class I>friend modint operator *(modint a,I b){return a*=b;}
    template<class I>friend modint operator /(modint a,I b){return a/=b;}
    friend modint operator ^(modint a,int b){return a^=b;}
    friend bool operator ==(modint a,int b){return a.x==b;}
    friend bool operator !=(modint a,int b){return a.x!=b;}
    bool operator ! () {return !x;}
    modint operator - () {return x?mod-x:0;}
};

#define maxn 105
#define inf 0x3f3f3f3f

int n,m;
int tot=1,ch[105][26];
bool ed[105];
inline void ins(string s)
{
	int u=1;
	for(int i=0;i<s.size();++i){
		int c=s[i]-'a';
		if(!ch[u][c])ch[u][c]=++tot;
		u=ch[u][c];
	}ed[u]=1;
}

int cnt=1;
bool ok[1605];
map<pii,int>mp;
queue<pii>q;
inline int id(pii x){
	if(!mp.count(x)){
		mp[x]=++cnt;
		if(ed[x.fi]&&ed[x.se])ok[cnt]=1;
		q.push(x); return cnt;
	}
	return mp[x];
}

struct mat{
	modint a[1605][1605];
	mat(){memset(a,0,sizeof a);}
	mat operator *(const mat&b)const{
		mat res;
		For(i,1,cnt)For(k,1,cnt)For(j,1,cnt)
			res.a[i][j]+=a[i][k]*b.a[k][j];
		return res;
	}
}t,s;

signed main()
{
	n=read(),m=read();
	For(i,1,n){
		string s; cin>>s;
		ins(s);
	}
	mp[mkp(1,1)]=1,q.push(mkp(1,1));
	while(!q.empty()){
		pii u=q.front(); q.pop();
		int idu=mp[u];
		For(c,0,25){
			if(ch[u.fi][c]&&ch[u.se][c])
				t.a[id(mkp(ch[u.fi][c],ch[u.se][c]))][idu]+=1;
			if(ed[u.fi] && ch[1][c] && ch[u.se][c])
				t.a[id(mkp(ch[1][c],ch[u.se][c]))][idu]+=1;
			if(ed[u.fi]&&ed[u.se]&&ch[1][c])
				t.a[id(mkp(ch[1][c],ch[1][c]))][idu]+=1;
			if(ed[u.se] && ch[1][c] && ch[u.fi][c])
				t.a[id(mkp(ch[u.fi][c],ch[1][c]))][idu]+=1;
		}
	}
	For(i,1,cnt) s.a[i][i]=1;
	for(;m;m>>=1,t=t*t)if(m&1)s=s*t;
	modint res=0;
	For(i,1,cnt)if(ok[i])res+=s.a[i][1];
	cout<<res.x;
    return 0;
}

#include <bits/stdc++.h>
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Rev(i,a,b) for(int i=a;i>=b;i--)
#define Fin(file) freopen(file,"r",stdin)
#define Fout(file) freopen(file,"w",stdout)
using namespace std;
const int N=305,mod=998244353; typedef long long ll;
int n,m,ch[N][26],tch[N][26],tot,w[N],q[N],h,t,nxt[N],num[N][N],px[N],py[N],cnt; char s[N];
struct Matrix{
    int a[N][N];
    int* operator[] (int x) { return a[x]; }
    friend Matrix operator* (Matrix& A,Matrix& B){
        Matrix C; For(i,1,cnt) For(j,1,cnt) { C[i][j]=0; For(k,1,cnt) C[i][j]=(C[i][j]+1ll*A[i][k]*B[k][j])%mod; } return C;
    }
}a,res;
int dfs(int x,int y){
    if(num[x][y]) return num[x][y];
    num[x][y]=++cnt; px[cnt]=x; py[cnt]=y;
    For(i,0,25){
        int x0=ch[x][i],y0=ch[y][i];
        if(x0&&y0){
            a[dfs(x0,y0)][num[x][y]]=1;
        }
    }
    if(x!=1&&w[x]){
        For(i,0,25){
            int x0=ch[1][i],y0=ch[y][i];
            if(x0&&y0){
                a[dfs(x0,y0)][num[x][y]]=1;
            }
        }
    }
    if(y!=1&&w[y]){
        For(i,0,25){
            int x0=ch[x][i],y0=ch[1][i];
            if(x0&&y0){
                a[dfs(x0,y0)][num[x][y]]=1;
            }
        }
    }
    if(x!=1&&w[x]&&y!=1&&w[y]){
        For(i,0,25){
            int x0=ch[1][i],y0=ch[1][i];
            if(x0&&y0){
                a[dfs(x0,y0)][num[x][y]]=1;
            }
        }
    }
    return num[x][y];
}
signed main(){
    cin>>n>>m; tot=1;
    For(i,1,n){
        cin>>(s+1); int l=strlen(s+1),p=1;
        For(o,1,l){
            int c=s[o]-'a'; if(!ch[p][c]){ch[p][c]=tch[p][c]=++tot;} p=ch[p][c];
        }
        w[p]=1;
    }
    dfs(1,1);
    // h=t=0; q[t++]=1; nxt[1]=0; For(i,0,25) tch[0][i]=1;
    // while(h<t) { int u=q[h++]; For(i,0,25) if(!tch[u][i]) tch[u][i]=tch[nxt[u]][i]; else { nxt[tch[u][i]]=tch[nxt[u]][i]; q[t++]=tch[u][i]; } }
    // For(u,1,tot){
    //     int v=u; while(v){
    //         num[u][v]=++cnt; px[cnt]=u; py[cnt]=v;
    //         if(u!=v) { num[v][u]=++cnt; px[cnt]=v; py[cnt]=u; }
    //         v=nxt[v];
    //     }
    // }
    // cout<<"cnt="<<cnt<<endl;
    // For(i,1,cnt){
    //     int u=px[i],v=py[i];
    //     For(c,0,25){
    //         int u0=ch[u][c],v0=ch[v][c]; if(!u0||!v0) continue;
    //         // assert(num[u0][v0]);
    //         a[num[u0][v0]][i]=1;
    //     }
    //     if(u!=1&&w[u]){
    //         For(c,0,25){
    //             int u0=ch[1][c],v0=ch[v][c]; if(!u0||!v0) continue;
    //             // assert(num[u0][v0]);
    //             a[num[u0][v0]][i]=1;
    //         }
    //     }
    //     if(v!=1&&w[v]){
    //         For(c,0,25){
    //             int u0=ch[u][c],v0=ch[1][c]; if(!u0||!v0) continue;
    //             // assert(num[u0][v0]);
    //             a[num[u0][v0]][i]=1;
    //         }
    //     }
    //     if(u!=1&&v!=1&&w[u]&&w[v]){
    //         For(c,0,25){
    //             int u0=ch[1][c],v0=ch[1][c]; if(!u0||!v0) continue;
    //             // assert(num[u0][v0]);
    //             a[num[u0][v0]][i]=1;
    //         }
    //     }
    // }
    For(i,1,cnt) res[i][i]=1;
    while(m) { if(m&1){res=res*a;} a=a*a; m>>=1; }
    // For(i,1,cnt){
    //     For(j,1,cnt) cout<<res[i][j]<<' ';
    //     cout<<endl;
    // }
    int ans=0;
    For(i,1,cnt) if(w[px[i]]&&w[py[i]]) ans=(ans+res[i][1])%mod;
    cout<<ans<<'\n';
    cerr<<"Time = "<<clock()<<" ms"<<endl;
    return 0;
}

// START TYPING IF YOU DON'T KNOW WHAT TO DO

#pragma GCC optimize("O1")
#include "bits/stdc++.h"
using namespace std;
#define all(x) begin(x),end(x)
typedef long long ll;
const long long MD = 998244353;
template<long long MOD> struct mdint {
    int d=0;
    mdint () {d=0;}
    mdint (long long _d) : d(_d%MOD){};
    friend mdint& operator+=(mdint& a, const mdint& o) {
        a.d+=o.d; if(a.d>=MOD) a.d-=MOD;
        return a;
    }
    friend mdint& operator-=(mdint& a, const mdint& o) {
        a.d-=o.d; if(a.d<0) a.d+=MOD;
        return a;
    }
    friend mdint& operator*=(mdint& a, const mdint& o) {
        return a = mdint((ll)a.d*o.d);
    }
    mdint operator*(const mdint& o) const {
        mdint res = *this;
        res*=o;
        return res;
    }
    mdint operator+(const mdint& o) const {
        mdint res = *this;
        res+=o;
        return res;
    }
    mdint operator-(const mdint& o) const {
        mdint res = *this;
        res-=o;
        return res;
    }
    mdint operator^(long long b) const {
        mdint tmp = 1;
        mdint power = *this;
        while(b) {
            if(b&1) {
                tmp = tmp*power;
            }
            power = power*power;
            b/=2;
        }
        return tmp;
    }
    friend mdint operator/=(mdint& a, const mdint& o) {
        a *= (o^(MOD-2));
        return a;
    }
    mdint operator/(const mdint& o) {
        mdint res = *this;
        res/=o;
        return res;
    }
    bool operator==(const mdint& o) { return d==o.d;}
    bool operator!=(const mdint& o) { return d!=o.d;}
    friend istream& operator>>(istream& c, mdint& a) {return c >> a.d;}
    friend ostream& operator<<(ostream& c, const mdint& a) {return c << a.d;}
};
typedef mdint<MD> mint;
#define rep(i,n) for(int i=0;i<n;++i)
template<typename T, int N> struct matrix {
    T mat[N][N];
    matrix() {
        rep(i,N) fill(mat[i],mat[i]+N,0);
    }
    friend matrix operator*(const matrix& a, const matrix& b) {
        matrix res;
        rep(i,N) rep(j,N) rep(k,N) {
            res.mat[i][k]+=a.mat[i][j]*b.mat[j][k];
        }
        return res;
    }
    static matrix eye() {
        matrix res;
        for(int i=0;i<N;++i) res.mat[i][i]=1;
        return res;
    }
    friend matrix pw(matrix& a, ll pwr) {
        matrix res = eye();
        while(pwr) {
            if(pwr&1) res=res*a;
            a=a*a;
            pwr/=2;
        }
        return res;
    }
};
matrix<mint,203> mat;
int id(int i, int j, int k) {
    return 1+(i*5+j)*5+k;
}
int main() {
    int n,m; cin >> n >> m;

    vector<string> ws(n);
    for(auto& i: ws) cin >> i;
    sort(all(ws),[&](const string& a, const string& b) {return a.size()<b.size();});

    for(int i=0;i<n;++i) {
        // from 0 to other state
        int sz = ws[i].size();
        for(int j=0;j<=i;++j) {
            if(ws[i].substr(0,ws[j].size()) == ws[j]) {
                if(sz==1) mat.mat[0][0]+=1;
                else mat.mat[0][id(i,sz-1,ws[j].size()-1)]+=1 + (i!=j);
            }
        }
        for(int j=1;j<sz;++j) {
            for(int k=1;k<=j;++k) {
                if(j==1 and k==1) {
                    mat.mat[id(i,j,k)][0]+=1;
                } else mat.mat[id(i,j,k)][id(i,j-1,k-1)]+=1;
            }
            for(int w=0;w<n;++w) {
                auto o = ws[w];
                int k = min(j,(int)o.size());
                if(o.substr(0,k)==ws[i].substr(sz-j,k)) {
                    if((int)o.size()<=j) {
                        if(j==1 and k==1) mat.mat[id(i,j,0)][0]+=1;
                        else mat.mat[id(i,j,0)][id(i,j-1,o.size()-1)]+=1;
                    } else mat.mat[id(i,j,0)][id(w,o.size()-1,j-1)]+=1;
                }
            }
        }
    }
    mat = pw(mat,m);
    cout << mat.mat[0][0].d << '\n';
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
#include <chrono>
#include <random>
#include <bitset>
#include <fstream>
using namespace std;
#define int long long
#define ii pair <int, int>
#define app push_back
#define all(a) a.begin(), a.end()
#define bp __builtin_popcountll
#define ll long long
#define mp make_pair
#define x first
#define y second
#define Time (double)clock()/CLOCKS_PER_SEC
#define debug(x) std::cerr << #x << ": " << x << '\n';
#define FOR(i, n) for (int i = 0; i < n; ++i)
#define FORN(i, n) for (int i = 1; i <= n; ++i)
#define pb push_back
#define trav(a, x) for (auto& a : x)
using vi = vector<int>;
template <typename T>
std::istream& operator >>(std::istream& input, std::vector<T>& data)
{
    for (T& x : data)
        input >> x;
    return input;
}
template <typename T>
std::ostream& operator <<(std::ostream& output, const pair <T, T> & data)
{
    output << "(" << data.x << "," << data.y << ")";
    return output;
}
template <typename T>
std::ostream& operator <<(std::ostream& output, const std::vector<T>& data)
{
    for (const T& x : data)
        output << x << " ";
    return output;
}
ll div_up(ll a, ll b) { return a/b+((a^b)>0&&a%b); } // divide a by b rounded up
ll div_down(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // divide a by b rounded down
ll math_mod(ll a, ll b) { return a - b * div_down(a, b); }
#define tcT template<class T
#define tcTU tcT, class U
tcT> using V = vector<T>;
tcT> void re(V<T>& x) {
    trav(a, x)
        cin >> a;
}
tcT> bool ckmin(T& a, const T& b) {
    return b < a ? a = b, 1 : 0;
} // set a = min(a,b)
tcT> bool ckmax(T& a, const T& b) {
    return a < b ? a = b, 1 : 0;
}
ll gcd(ll a, ll b) {
    while (b) {
        tie(a, b) = mp(b, a % b);
    }
    return a;
}

//need define int long long
namespace Stuff {
const int MOD = 998244353;
int mod(int n) {
    n %= MOD;
    if (n < 0) return n + MOD;
    else return n;
}
int fp(int a, int p) {
    int ans = 1, c = a;
    for (int i = 0; (1ll << i) <= p; ++i) {
        if ((p >> i) & 1) ans = mod(ans * c);
        c = mod(c * c);
    }
    return ans;
}
int dv(int a, int b) { return mod(a * fp(b, MOD - 2)); }
};
struct M {
ll x;
M (int x_) { x = Stuff::mod(x_); }
M () { x = 0; }
M operator + (M y) {
    int ans = x + y.x;
    if (ans >= Stuff::MOD)
        ans -= Stuff::MOD;
    return M(ans);
}
M operator - (M y) {
    int ans = x - y.x;
    if (ans < 0)
        ans += Stuff::MOD;
    return M(ans);
}
M operator * (M y) { return M(x * y.x % Stuff::MOD); }
M operator / (M y) { return M(x * Stuff::fp(y.x, Stuff::MOD - 2) % Stuff::MOD); }
M operator + (int y) { return (*this) + M(y); }
M operator - (int y) { return (*this) - M(y); }
M operator * (int y) { return (*this) * M(y); }
M operator / (int y) { return (*this) / M(y); }
M operator ^ (int p) { return M(Stuff::fp(x, p)); }
void operator += (M y) { *this = *this + y; }
void operator -= (M y) { *this = *this - y; }
void operator *= (M y) { *this = *this * y; }
void operator /= (M y) { *this = *this / y; }
void operator += (int y) { *this = *this + y; }
void operator -= (int y) { *this = *this - y; }
void operator *= (int y) { *this = *this * y; }
void operator /= (int y) { *this = *this / y; }
void operator ^= (int p) { *this = *this ^ p; }
bool operator == (M y) { return x == y.x; }
};
std::ostream& operator << (std::ostream& o, const M& a)
{
    cout << a.x;
    return o;
}

const int N = 57, C = 26, LG = 40;
int ptr = 1;
int par[N], len[N], trie[N][C], last[N];
bool term[N];
int term_link[N];

const int S = 200;
M dp[LG][S][S];
M cur[S], nu[S];

int go[N][N][N][N];

bool used[N][N];
void dfs(int u, int v) {
    used[u][v] = 1;
    FOR (uu, N) {
        FOR (vv, N) {
            if (go[u][v][uu][vv] && !used[uu][vv]) {
                dfs(uu, vv);
            }
        }
    }
}

int sz = 0;
int num[N][N];

signed main() {
    #ifdef LOCAL
    #else
    #define endl '\n'
    ios_base::sync_with_stdio(0); cin.tie(0);
    #endif

    int n, m;
    cin >> n >> m;
    V <string> a(n);
    cin >> a;
    trav (s, a) {
        int u = 0;
        trav (c, s) {
            if (!trie[u][c - 'a']) {
                trie[u][c - 'a'] = ptr;
                len[ptr] = len[u] + 1;
                par[ptr] = u;
                last[ptr] = c - 'a';
                ptr++;
            }
            u = trie[u][c - 'a'];
        }
        term[u] = 1;
    }

    FOR (u, ptr) {
        FOR (v, ptr) {
            FOR (c, C) {
                if (trie[u][c] && trie[v][c]) {
                    int uu = trie[u][c];
                    int vv = trie[v][c];
                    go[u][v][uu][vv]++;
                    if (term[uu]) {
                        go[u][v][0][vv]++;
                    }
                    if (term[vv]) {
                        go[u][v][uu][0]++;
                    }
                    if (term[uu] && term[vv]) {
                        go[u][v][0][0]++;
                    }
                }
            }
        }
    }

    dfs(0, 0);

    FOR (u, ptr) {
        FOR (v, ptr) {
            if (used[u][v]) {
                num[u][v] = sz;
                sz++;
            }
        }
    }

    assert(sz < 200);

    FOR (u, ptr) {
        FOR (v, ptr) {
            if (used[u][v]) {
                FOR (uu, ptr) {
                    FOR (vv, ptr) {
                        if (used[uu][vv]) {
                            dp[0][num[u][v]][num[uu][vv]] = go[u][v][uu][vv];
                        }
                    }
                }
            }
        }
    }

    FORN (t, LG - 1) {
        FOR (u, sz) {
            FOR (v, sz) {
                FOR (k, sz) {
                    dp[t][u][v] += dp[t - 1][u][k] * dp[t - 1][k][v];
                }
            }
        }
    }

    cur[0] = 1;
    FOR (p, LG) {
        if ((m >> p) & 1) {
            FOR (i, sz) {
                nu[i] = 0;
            }
            FOR (i, sz) {
                FOR (j, sz) {
                    nu[j] += cur[i] * dp[p][i][j];
                }
            }
            FOR (i, sz) {
                cur[i] = nu[i];
            }
        }
    }
    cout << cur[0] << endl;
}

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int maxn=45,maxt=205,mod=998244353;
int n,m,tot,cnt;
int nxt[maxn][27],ed[maxn],id[maxn][maxn];
string s;
struct matrix{
	int len,wid;
	int a[maxt][maxt];
	matrix operator *(const matrix p){
		matrix res;
		res.len=len,res.wid=p.wid,memset(res.a,0,sizeof(res.a));
		for(int i=1;i<=len;i++)
			for(int j=1;j<=p.wid;j++)
				for(int k=1;k<=wid;k++)
					res.a[i][j]=(res.a[i][j]+1ll*a[i][k]*p.a[k][j])%mod;
		return res;
	}
	matrix operator ^(long long b){
		matrix a=(*this),res;
		res.len=res.wid=len,memset(res.a,0,sizeof(res.a));
		for(int i=1;i<=len;i++)
			res.a[i][i]=1;
		while(b){
			if(b&1)
				res=res*a;
			a=a*a,b>>=1;
		}
		return res;
	}
}T;
void insert(string s){
	int now=1;
	for(int i=0;i<s.size();i++){
		int c=s[i]-96;
		if(nxt[now][c]==0)
			nxt[now][c]=++tot;
		now=nxt[now][c];
	}
	ed[now]=1;
}
void dfs(int a,int b){
	if(a>b){
		dfs(b,a),id[a][b]=id[b][a];
		return ;
	}
	if(id[a][b])
		return ;
	id[a][b]=++cnt;
	for(int i=1;i<=26;i++)
		if(nxt[a][i]&&nxt[b][i]){
			int c=nxt[a][i],d=nxt[b][i];
			dfs(c,d),T.a[id[a][b]][id[c][d]]++;
			if(ed[c])
				dfs(1,d),T.a[id[a][b]][id[1][d]]++;
			if(ed[d])
				dfs(c,1),T.a[id[a][b]][id[c][1]]++;
			if(ed[c]&&ed[d])
				T.a[id[a][b]][1]++;
		}
}
int main(){
	scanf("%d%d",&n,&m),tot=1;
	for(int i=1;i<=n;i++)
		cin>>s,insert(s);
	memset(T.a,0,sizeof(T.a)),dfs(1,1),T.len=T.wid=cnt;
	printf("%d\n",(T^m).a[1][1]);
	return 0;
}
//?

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int read()
{
	int ret=0;bool f=0;char c=getchar();
	while(c>'9'||c<'0')f|=(c=='-'),c=getchar();
	while(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+(c^48),c=getchar();
	return f?-ret:ret;
}
const int maxn=160;
const int mod=998244353;
int n,m;
map<pair<int,int>,int>id;
struct matrix
{
	int num[maxn][maxn];
	matrix(){memset(num,0,sizeof num);}
	matrix operator *(const matrix &x)
	{
		matrix ret;
		for(int i=0;i<id.size();i++)
			for(int j=0;j<id.size();j++)
				for(int k=0;k<id.size();k++)
					(ret.num[i][j]+=(ll)num[i][k]*x.num[k][j]%mod)%=mod;
		return ret;
	}
	friend matrix qpow(matrix a,int b)
	{
		matrix ret;for(int i=0;i<id.size();i++)ret.num[i][i]=1;
		for(;b;b>>=1,a=a*a)if(b&1)ret=ret*a;
		return ret;
	}
}tran,ans;
struct trie
{
	#define S(u,i) t[u].ch[i]
	struct node{int ch[26];bool ed;}t[maxn];int cnt;
	void insert(string &s)
	{
		int p=0;
		for(char &c:s)
		{
			if(!S(p,c-'a'))S(p,c-'a')=++cnt;
			p=S(p,c-'a');
		}
		t[p].ed=1;
	}
	void dfs(int u1,int u2)
	{
		if(u1>u2)swap(u1,u2);
		if(id.count({u1,u2}))return;
		if(u1&&u2){int tmp=id.size();id[{u1,u2}]=tmp;}
		for(int i=0;i<26;i++)
			if(S(u1,i)&&S(u2,i))dfs(S(u1,i),S(u2,i));
	}
	void getid(){for(int i=0;i<=cnt;i++)dfs(0,i);}
	void getmat()
	{
		for(auto &i:id)
		{
			int x=i.first.first,y=i.first.second;
			for(int j=0;j<26;j++)
				if(S(x,j)&&S(y,j))
				{
					int tox=S(x,j),toy=S(y,j);
					if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
				}
			if(t[x].ed)
				for(int j=0;j<26;j++)
					if(S(0,j)&&S(y,j))
					{
						int tox=S(0,j),toy=S(y,j);
						if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
					}
			if(t[y].ed)
				for(int j=0;j<26;j++)
					if(S(x,j)&&S(0,j))
					{
						int tox=S(x,j),toy=S(0,j);
						if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
					}
			if(t[x].ed&&t[y].ed)
				for(int j=0;j<26;j++)
					if(S(0,j)&&S(0,j))
					{
						int tox=S(0,j),toy=S(0,j);
						if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
					}
			if(x!=y)
			{
				swap(x,y);
				for(int j=0;j<26;j++)
				if(S(x,j)&&S(y,j))
				{
					int tox=S(x,j),toy=S(y,j);
					if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
				}
				if(t[x].ed)
					for(int j=0;j<26;j++)
						if(S(0,j)&&S(y,j))
						{
							int tox=S(0,j),toy=S(y,j);
							if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
						}
				if(t[y].ed)
					for(int j=0;j<26;j++)
						if(S(x,j)&&S(0,j))
						{
							int tox=S(x,j),toy=S(0,j);
							if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
						}
				if(t[x].ed&&t[y].ed)
					for(int j=0;j<26;j++)
						if(S(0,j)&&S(0,j))
						{
							int tox=S(0,j),toy=S(0,j);
							if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
						}
			}
		}
		for(int i=0;i<26;i++)
			if(S(0,i))ans.num[0][id[{S(0,i),S(0,i)}]]++;
	}
	#undef S
}tr;
int f[maxn];
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;i++){string s;cin>>s;tr.insert(s);}
	tr.getid();tr.getmat();
	ans=ans*qpow(tran,m-1);
	int sum=0;
	for(auto &i:id)
		if(tr.t[i.first.first].ed&&tr.t[i.first.second].ed)
			sum=((ll)sum+(1+(i.first.first!=i.first.second))*ans.num[0][i.second])%mod;
	printf("%d\n",sum);
	return 0;
}

#include<bits/stdc++.h>
#define rfor(x...)for(register x)
#define rep(i,l,r)rfor(ll i=l;i<=r;i++)
#define per(i,l,r)rfor(ll i=l;i>=r;i--)
#define ref(i,l,r)rfor(ll i=l;i<r;i++)
#define IO(x...)freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
typedef long long ll;const ll N=1e6+7,mod=998244353,mod2=mod*mod;typedef ll aN[N];aN son[26],w;ll cnt=1;
ll readll(){
    ll x=0,w=1;int c=getchar();for(;c<'0'||c>'9';c-'-'||(w=-w),c=getchar());
    for(;c>='0'&&c<='9';x=x*10+(c^48),c=getchar());return x*w;
}int readchar(int l='0',int r='z'){if(l>r)std::swap(l,r);int c=getchar();for(;c<l||c>r;c=getchar());return c;}
void lim(ll&a,ll b){if(a>b)a-=b;}
struct mtr{
    ll n,m,val[200][200];void set(ll n_,ll m_,int clear=1){n=n_,m=m_;if(clear)memset(val,0,sizeof val);}
    ll*operator[](ll b){return val[b];}const ll*operator[](ll b)const{return val[b];}
}f,g;mtr operator*(const mtr&a,const mtr&b){
    mtr res;ll n=a.n,m=a.m,t=b.m;res.set(n,t);rep(k,1,m)rep(i,1,n)rep(j,1,t)lim(res[i][j]+=a[i][k]*b[k][j],mod2);
    rep(i,1,n)rep(j,1,t)res[i][j]%=mod;return res;
}void pow(mtr&res,mtr a,ll b){while(b){if(b&1)res=res*a;a=a*a,b>>=1;}}ll id[44][44],top;char s[122][122];
void insert(const char*s){ll now=1;while(*s)now=son[*s-'a'][now]?:son[*s-'a'][now]=++cnt,s++;++w[now];}
ll dfs(ll u,ll v){//printf("%lld %lld\n",u,v);
    if(id[u][v]|id[v][u])return id[u][v]|id[v][u];ll res=id[u][v]=++top,*to=f[res],su,sv;
    rep(i,0,25)if(son[i][u]&&son[i][v])su=son[i][u],sv=son[i][v],to[dfs(su,sv)]++,w[su]&&(to[dfs(1,sv)]+=w[su]),
    w[sv]&&(to[dfs(su,1)]+=w[sv]),to[1]+=w[su]*w[sv];return res;
}
int main(){//exit(0);
    ll n=readll(),m=readll();rep(i,1,n)scanf("%s",s[i]+1),insert(s[i]+1);//exit(0);
//    rep(i,0,25)rep(j,1,cnt)if(son[i][j])printf("%lld %lld %c\n",j,son[i][j],(int)i+'a');
    dfs(1,1),f.set(top,top,0),g.set(1,top);g[1][1]=1;pow(g,f,m);printf("%lld\n",g[1][1]);return 0;
}

#include<bits/stdc++.h>
#define mk make_pair
using namespace std;
const int N=233;
const int p=998244353;

int read()
{
	int s=0;
	char c=getchar(),lc='+';
	while (c<'0'||'9'<c) lc=c,c=getchar();
	while ('0'<=c&&c<='9') s=s*10+c-'0',c=getchar();
	return lc=='-'?-s:s;
}
void write(int x)
{
	if (x<0) putchar('-'),x=-x;
	if (x<10) putchar(x+'0');
	else write(x/10),putchar(x%10+'0');
}
void print(int x=-1,char c='\n')
{
	write(x);
	putchar(c);
}
void add(int &x,int y){x+=y;if (x>=p) x-=p;}
int cnt,id[50][50],vis[50][50];
struct Matrix{int a[N][N];}tr;
struct Vector{int a[N];}f;
Matrix operator *(const Matrix &a,const Matrix &b)
{
	Matrix ret;
	memset(ret.a,0,sizeof(ret.a));
	for (int i=1;i<=cnt;i++)
	for (int k=1;k<=cnt;k++)
	for (int j=1;j<=cnt;j++)
	add(ret.a[i][j],1LL*a.a[i][k]*b.a[k][j]%p);
	return ret;
}
Vector operator *(const Vector &a,const Matrix &b)
{
	Vector ret;
	memset(ret.a,0,sizeof(ret.a));
	for (int i=1;i<=cnt;i++)
	for (int j=1;j<=cnt;j++)
	add(ret.a[j],1LL*a.a[i]*b.a[i][j]%p);
	return ret;
}
char a[10];
struct trie
{
	int cnt;
	struct node
	{
		int son[26],end,down;
	}t[50];
	void insert(char *a,int len)
	{
		int now=0;
		#define to t[now].son[a[i]-'a']
		for (int i=1;i<=len;i++)
		{
			if (!to) to=++cnt;
			now=to;
		}
		t[now].end=1;
		#undef to
	}
	void ysgs()
	{
		for (int i=0;i<=cnt;i++)
		for (int j=0;j<26;j++) t[i].down|=!!t[i].son[j];
	}
	void dfs(int u,int v)
	{
		if (vis[u][v]) return;
		vis[u][v]=1;
		for (int k=0;k<26;k++)
		if (t[u].son[k]&&t[v].son[k])
		{
			int nu=t[u].son[k],nv=t[v].son[k];
			for (int i=!t[nu].down;i<=t[nu].end;i++)
			for (int j=!t[nv].down;j<=t[nv].end;j++)
			{
				if (i) nu=0; if (j) nv=0;
				dfs(nu,nv);
				nu=t[u].son[k],nv=t[v].son[k];
			}
		}
	}
	void build()
	{
		for (int u=0;u<=cnt;u++)
		for (int v=u;v<=cnt;v++)
		if (id[u][v])
		for (int k=0;k<26;k++)
		if (t[u].son[k]&&t[v].son[k])
		{
			int nu=t[u].son[k],nv=t[v].son[k];
			for (int i=!t[nu].down;i<=t[nu].end;i++)
			for (int j=!t[nv].down;j<=t[nv].end;j++)
			{
				if (i) nu=0; if (j) nv=0;
				tr.a[id[u][v]][id[nu][nv]]+=1+(!nu&&!nv&&u!=v)-(u==v&&i!=j?tr.a[id[u][v]][id[nu][nv]]:0);
//				print(id[u][v],' ');
//				print(id[nu][nv],':');
//				print(tr.a[id[u][v]][id[nu][nv]]);
				nu=t[u].son[k],nv=t[v].son[k];
			}
		}
	}
}t;

signed main(signed Goodbye,char *Wangang[])
{
	(void)Goodbye,(void)Wangang;
	int n=read(),m=read();
	for (int i=1;i<=n;i++)
	{
		scanf("%s",a+1);
		t.insert(a,strlen(a+1));
	}
	t.ysgs();
	t.dfs(0,0);
	for (int i=0;i<=t.cnt;i++)
	for (int j=i;j<=t.cnt;j++)
	if (vis[i][j]) id[i][j]=id[j][i]=++cnt;
	t.build();
	f.a[1]=1;
	while (m)
	{
		if (m&1) f=f*tr;
		tr=tr*tr;
		m/=2;
	}
	print(f.a[1]);

	return 0;
}

/*
 *   ##   #####   ####      ####  #    #  ####
 *  #  #  #    # #    #    #    # #    # #    #
 * #    # #####  #         #    # #    # #    #
 * ###### #    # #         #    # # ## # #    #
 * #    # #    # #    #    #    # ##  ## #    #
 * #    # #####   ####      ####  #    #  ####
 */
#include <bits/stdc++.h>
using namespace std;
#define lli long long int
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define pii pair <int, int>
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define info() cout << __PRETTY_FUNCTION__ << ": " << __LINE__ << endl
void abc() {cout << endl;}
template <typename T, typename ...U> void abc(T a, U ...b) {
    cout << a << ' ', abc(b...);
}
template <typename T> void printv(T l, T r) {
    for (; l != r; ++l) cout << *l << " \n"[l + 1 == r];
}
template <typename A, typename B> istream& operator >> (istream& o, pair<A, B> &a) {
    return o >> a.X >> a.Y;
}
template <typename A, typename B> ostream& operator << (ostream& o, pair<A, B> a) {
    return o << '(' << a.X << ", " << a.Y << ')';
}
template <typename T> ostream& operator << (ostream& o, vector<T> a) {
    bool is = false;
    if (a.empty()) return o << "{}";
    for (T i : a) {o << (is ? ' ' : '{'), is = true, o << i;}
    return o << '}';
}
template <typename T> struct vv : vector <vector <T>> {
    vv(int n, int m, T v) : vector <vector <T>> (n, vector <T>(m, v)) {}
    vv() {}
};
template <typename T> struct vvv : vector <vv <T>> {
    vvv(int n, int m, int k, T v) : vector <vv <T>> (n, vv <T>(m, k, v)) {}
    vvv() {}
};
#ifdef Doludu
#define test(args...) abc("[" + string(#args) + "]", args)
#define owo freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout);
#else
#define test(args...) void(0)
#define owo ios::sync_with_stdio(false); cin.tie(0)
#endif
const int mod = 998244353, N = 300001, logN = 19, K = 1 << 9;

struct mat {
    int n;
    long long mod2;
    vector <vector <long long>> val;
    mat (int _n, int _mode = 0) : n(_n), mod2(1ll * mod * mod) {
        // mode 1 -> I, other -> O
        val.assign(n, vector<long long>(n, 0));
        if (_mode == 1) {
            for (int i = 0; i < n; ++i) val[i][i] = 1;
        }
    }
    mat (const mat& M) : n(M.n), mod2(1ll * mod * mod) {
        val.assign(n, vector<long long>(n, 0));
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                val[i][j] = M.val[i][j];
            }
        }
    }
    mat (vector <vector <long long>> v) : n(v.size()), mod2(1ll * mod * mod), val(v) {}
    mat operator + (const mat& o) {
        mat ans(o);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                ans.val[i][j] += val[i][j];
                if (ans.val[i][j] >= mod) ans.val[i][j] -= mod;
            }
        }
        return ans;
    }
    mat operator * (const mat& o) {
        mat ans(n, 0);
        for (int i = 0; i < n; ++i) {
            for (int k = 0; k < n; ++k) {
                for (int j = 0; j < n; ++j) {
                    ans.val[i][j] += val[i][k] * o.val[k][j];
                    if (ans.val[i][j] >= mod2) ans.val[i][j] -= mod2;
                }
            }
        }
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                ans.val[i][j] %= mod;
            }
        }
        return ans;
    }
    mat operator ^ (long long k) {
        mat ans(n, 1), a(*this);
        for (; k; k >>= 1, a = a * a) {
            if (k & 1) ans = ans * a;
        }
        return ans;
    }
};

int main() {
    owo;
    int n, m;
    cin >> n >> m;
    vector <string> pre;
    vector <int> fin;
    pre.pb(""), fin.pb(0);
    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 1; j <= s.length(); ++j) {
            if (find(all(pre), s.substr(0, j)) == pre.end()) {
                pre.pb(s.substr(0, j)), fin.pb(0);
            }
        }
        fin[find(all(pre), s) - pre.begin()] = 1;
    }
    vector <pii> dim;
    for (int i = 0; i < pre.size(); ++i) {
        for (int j = i; j < pre.size(); ++j) {
            string s = pre[i], t = pre[j];
            if (s.length() > t.length())
                swap(s, t);
            if (t.substr(t.length() - s.length()) == s) {
                dim.eb(i, j);
            }
        }
    }
    auto append = [&](int i, char c) {
        if (find(all(pre), pre[i] + c) != pre.end()) {
            return find(all(pre), pre[i] + c) - pre.begin();
        }
        return -1;
    };
    n = dim.size();
    vv <long long> a(n, n, 0);
    function<void(int, int, int)> add_ma = [&](int i, int l, int r) {
        if (find(all(dim), mp(l, r)) != dim.end())
            a[find(all(dim), mp(l, r)) - dim.begin()][i]++;
    };
    for (int i = 0; i < n; ++i) {
        for (char c = 'a'; c <= 'z'; ++c) {
            int l, r;
            tie(l, r) = dim[i];
            l = append(l, c), r = append(r, c);
            if (l == -1 || r == -1)
                continue;
            if (l > r)
                swap(l, r);
            add_ma(i, l, r);
            if (fin[l])
                add_ma(i, 0, r);
            if (fin[r])
                add_ma(i, 0, l);
            if (fin[l] && fin[r])
                add_ma(i, 0, 0);
        }
    }
    mat M(a);
    M = M ^ m;
    cout << M.val[0][0] << endl;
}

#include <bits/stdc++.h>

#define fi first
#define se second
#define DB double
#define U unsigned
#define P std::pair
#define LL long long
#define LD long double
#define pb emplace_back
#define MP std::make_pair
#define SZ(x) ((int)x.size())
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 8 + 5;
const int MAXM = 168 + 5;
const int ha = 998244353;

inline void add(int &x,int y){
    x += y-ha;x += x>>31&ha;
}

int N;
struct Matrix{
    int a[MAXM][MAXM];
    Matrix(){CLR(a,0);}
    inline int* operator [] (const int &n){return a[n];}
    inline const int* operator [] (const int &n) const {return a[n];}

    Matrix operator * (const Matrix &t) const {
        Matrix res;
        FOR(i,0,N-1) FOR(j,0,N-1) FOR(k,0,N-1) add(res.a[i][j],1ll*a[i][k]*t.a[k][j]%ha);
        return res;
    }
}A;

Matrix qpow(Matrix a,int n){
    Matrix res;FOR(i,0,N-1) res.a[i][i] = 1;
    while(n){
        if(n&1) res = res*a;
        a = a*a;
        n >>= 1;
    }
    return res;
}

int n,m;
int ch[MAXM][26],tot=1;
int id[MAXM][MAXM];
char str[MAXN];
bool vis[MAXM];

inline void insert(char str[]){
    int len = strlen(str+1),v = 1;
    FOR(i,1,len){
        int o = str[i]-'a';
        if(!ch[v][o]) ch[v][o] = ++tot;
        v = ch[v][o];
    }
    vis[v] = 1;
}

inline void upd(int x,int y){// x -> y
    add(A[y][x],1);
}

inline int gao(int x,int y){
    if(x > y) std::swap(x,y);
    if(id[x][y] != -1) return id[x][y];
    id[x][y] = N++;int v = id[x][y];
    FOR(i,0,25){
        if(ch[x][i] && ch[y][i]){
            int xx = ch[x][i],yy = ch[y][i];
            upd(v,gao(xx,yy));
            if(vis[xx]) upd(v,gao(1,yy));
            if(vis[yy]) upd(v,gao(xx,1));
            if(vis[xx] && vis[yy]) upd(v,gao(1,1));
        }
    }
    return v;
}

int main(){

    scanf("%d%d",&n,&m);
    CLR(id,-1);
    FOR(i,1,n){
        scanf("%s",str+1);
        insert(str);
    }
    gao(1,1);
    A = qpow(A,m);
    printf("%d\n",A[0][0]);
    return 0;
}

#include <bits/stdc++.h>

#define ll long long
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define vi vector<int>
#define pii pair<int, int>
#define rep(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;
template<typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

template<int m>
struct mod {
    long long x;
    mod() : x(0) {}
    mod(long long xx) : x(xx) {
        if(abs(x) >= m) x %= m;
        if(x < 0) x += m;
    }
    mod operator+(const mod &a) const {
        mod n;
        n.x = x + a.x;
        if(n.x >= m) n.x -= m;
        return n;
    }
    mod operator-(const mod &a) const {
        mod n;
        n.x = x - a.x;
        if(n.x < 0) n.x += m;
        return n;
    }
    mod operator*(const mod &a) const {
        return x * a.x;
    }
    mod operator+=(const mod &a) {
        x += a.x;
        if(x >= m) x -= m;
        return *this;
    }
    mod operator-=(const mod &a) {
        x -= a.x;
        if(x < 0) x += m;
        return *this;
    }
    mod operator*=(const mod &a) {
        x = (x * a.x) % m;
        return *this;
    }
    mod pow(long long b) const {
        mod ans = 1;
        mod a = *this;
        while(b > 0) {
            if(b & 1) ans *= a;
            a *= a;
            b /= 2;
        }
        return ans;
    }
    mod inv() const {
        return pow(m - 2);
    }
    mod operator/(const mod &a) const {
        return (*this) * a.inv();
    }
    mod operator/=(const mod &a) {
        return (*this) *= a.inv();
    }
    bool operator==(const mod &o) const {
        return x == o.x;
    }
    bool operator!=(const mod &o) const {
        return x != o.x;
    }
    long long operator()() const {
        return x;
    }
};

template<int m>
istream &operator>>(istream &is, mod<m> &n) {
    long long x;
    is >> x;
    n = x;
    return is;
}

template<int m>
ostream &operator<<(ostream &os, const mod<m> &n) {
    return os << n();
}

template<typename T, int N, int M>
struct mat : array<array<T, M>, N> {
    mat(T diag = T()) {
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < M; j++) {
                if(i == j) {
                    (*this)[i][j] = diag;
                }else {
                    (*this)[i][j] = T();
                }
            }
        }
    }
    mat<T, N, M> operator+(const mat<T, N, M> &o) const {
        mat<T, N, M> X;
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < M; j++) {
                X[i][j] = (*this)[i][j] + o[i][j];
            }
        }
        return X;
    }
    template<int P>
    mat<T, N, P> operator*(const mat<T, M, P> &o) const {
        mat<T, N, P> X;
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < P; j++) {
                for(int k = 0; k < M; k++) {
                    X[i][j] += (*this)[i][k] * o[k][j];
                }
            }
        }
        return X;
    }
    array<T, N> operator*(const array<T, M> &x) const {
        array<T, N> y{};
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < M; j++) {
                y[i] += (*this)[i][j] * x[j];
            }
        }
        return y;
    }
    mat<T, N, M> pow(long long b) const {
        mat A = *this;
        mat X(1);
        while(b > 0) {
            if(b & 1) X = X * A;
            A = A * A;
            b /= 2;
        }
        return X;
    }
    mat<T, M, N> t() const {
        mat<T, M, N> X;
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < M; j++) {
                X[j][i] = (*this)[i][j];
            }
        }
        return X;
    }
};

template<typename T, int N, int M>
ostream& operator<<(ostream &os, const mat<T, N, M> &A) {
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < M; j++) {
            os << A[i][j] << ' ';
        }
        os << '\n';
    }
    return os;
}

const int M = 998244353;
using base = mod<M>;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    vector<string> s(n);
    rep(i, 0, n) {
        cin >> s[i];
    }
    mat<base, 175, 175> A;
    rep(x, 0, 35) {
        int i = x / 5;
        int p = x % 5;
        rep(b, 0, 4) A[x + 35 * (b + 1)][x + 35 * b] += 1;
        if(i < n && p < (int) s[i].length()) {
            if(p == (int) s[i].length() - 1) {
                rep(j, 0, n) rep(k, 0, n) {
                    int l = min(s[j].length(), s[k].length());
                    if(s[j].substr(0, l) == s[k].substr(0, l)) {
                        int y = (s[j].length() >= s[k].length() ? 5 * j + l - 1 : 5 * k + l - 1);
                        A[y][x + 35 * (l - 1)] += 1;
                    }
                }
            }else {
                rep(j, 0, n) {
                    int l = min(s[j].length(), s[i].length() - p - 1);
                    if(s[j].substr(0, l) == s[i].substr(p + 1, l)) {
                        int y = ((int) s[j].length() >= (int) s[i].length() - p - 1 ? 5 * j + l - 1 : 5 * i + p + l);
                        A[y][x + 35 * (l - 1)] += 1;
                    }
                }
            }
        }
    }

    array<base, 175> vec;
    vec[s[0].length() - 1] = 1;
    vec = A.pow(m) * vec;
    base ans = 0;
    rep(i, 0, n) ans += vec[5 * i + s[i].length() - 1];
    cout << ans << '\n';
}

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
typedef long long llint;

const int MOD = 998244353;

int mod_add(int x, int y) { return (x + y) % MOD; }

int mod_sub(int x, int y) { return (x - y + MOD) % MOD; }

int mod_mult(int x, int y) { return static_cast<int>(llint(x) * y % MOD); }

int mod_pow(int x, int y) {
  int ret = 1;
  int curr = x, p = y;
  while (p != 0) {
    if (p & 1) {
      ret = mod_mult(ret, curr);
    }
    curr = mod_mult(curr, curr);
    p >>= 1;
  }
  return ret;
}

int mod_div(int x, int y) { return mod_mult(x, mod_pow(y, MOD - 2)); }

const int S = 1000;
const int A = 26;
struct Node {
  bool terminal;
  int next[A];
};
int ncnt;
Node nodes[S];

int n, m;
vector<string> words;
int res;

bool readin() {
  if (!(cin >> n >> m)) {
    return false;
  }
  words.resize(n);
  for (int i = 0; i < n; ++i) {
    cin >> words[i];
  }
  return true;
}

typedef vector<vector<int>> Matrix;

void matrix_copy(const Matrix &a, Matrix &b) {
  int n = a.size();
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      b[i][j] = a[i][j];
    }
  }
}

void matrix_mult(const Matrix &a, const Matrix &b, Matrix &c) {
  int n = a.size();
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      c[i][j] = 0;
      for (int k = 0; k < n; ++k) {
        c[i][j] = mod_add(c[i][j], mod_mult(a[i][k], b[k][j]));
      }
    }
  }
}

void matrix_pow(const Matrix &a, int r, Matrix &b) {
  int n = a.size();
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      b[i][j] = (i == j ? 1 : 0);
    }
  }
  Matrix a_copy = a;
  Matrix tmp(n, vector<int>(n));
  while (r > 0) {
    if (r % 2 != 0) {
      matrix_copy(b, tmp);
      matrix_mult(tmp, a_copy, b);
    }
    matrix_copy(a_copy, tmp);
    matrix_mult(tmp, tmp, a_copy);
    r /= 2;
  }
}

int allocate_node() {
  fill(nodes[ncnt].next, nodes[ncnt].next + A, -1);
  nodes[ncnt].terminal = false;
  return ncnt++;
}

void add_word(Node &root, const string &word) {
  Node *curr = &root;
  for (string::size_type i = 0; i < word.size(); ++i) {
    if (curr->next[word[i] - 'a'] == -1) {
      curr->next[word[i] - 'a'] = allocate_node();
    }
    curr = &nodes[curr->next[word[i] - 'a']];
  }
  curr->terminal = true;
}

void solve() {
  ncnt = 0;
  allocate_node();
  Node &root = nodes[0];
  for (const auto &word : words) {
    add_word(root, word);
  }
  queue<pair<int, int>> q;
  map<pair<int, int>, int> mp;
  set<int> terminate_states;
  set<pair<int, int>> transitions;
  q.push(make_pair(0, 0));
  mp[make_pair(0, 0)] = mp.size();
  while (!q.empty()) {
    auto s = q.front();
    q.pop();
    for (int a = 0; a < A; ++a) {
      int u = nodes[s.first].next[a], v = nodes[s.second].next[a];
      if (u == -1 || v == -1) {
        continue;
      }
      int tmp;
      if (mp.find(make_pair(u, v)) == mp.end()) {
        q.push(make_pair(u, v));
        tmp = mp[make_pair(u, v)] = mp.size();
        transitions.insert(make_pair(mp[s], tmp));
        if (nodes[u].terminal && nodes[v].terminal) {
          terminate_states.insert(tmp);
          transitions.insert(make_pair(mp[s], 0));
        }
      } else {
        tmp = mp[make_pair(u, v)];
        transitions.insert(make_pair(mp[s], tmp));
        if (nodes[u].terminal && nodes[v].terminal) {
          transitions.insert(make_pair(mp[s], 0));
        }
      }
      if (nodes[u].terminal) {
        if (mp.find(make_pair(0, v)) == mp.end()) {
          q.push(make_pair(0, v));
          tmp = mp[make_pair(0, v)] = mp.size();
          transitions.insert(make_pair(mp[s], tmp));
        } else {
          tmp = mp[make_pair(0, v)];
          transitions.insert(make_pair(mp[s], tmp));
        }
      }
      if (nodes[v].terminal) {
        if (mp.find(make_pair(u, 0)) == mp.end()) {
          q.push(make_pair(u, 0));
          tmp = mp[make_pair(u, 0)] = mp.size();
          transitions.insert(make_pair(mp[s], tmp));
        } else {
          tmp = mp[make_pair(u, 0)];
          transitions.insert(make_pair(mp[s], tmp));
        }
      }
    }
  }
  int N = mp.size();
  Matrix a(N, vector<int>(N));
  for (const auto &t : transitions) {
    a[t.second][t.first] = 1;
  }
  Matrix b(N, vector<int>(N));
  matrix_pow(a, m, b);
  res = 0;
  for (int i = 0; i < N; ++i) {
    if (terminate_states.find(i) != terminate_states.end()) {
      res = mod_add(res, b[i][0]);
    }
  }
  cout << res << endl;
}

int main() {
  while (readin()) {
    solve();
  }
  return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <iomanip>
#define endl '\n'
#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ldb;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef pair<LL, int> pli;
typedef pair<int, long> pil;
const int INF = 0x3f3f3f3f;
inline int read(){
    register int x; register char c(getchar()); register bool k;
    while((c < '0' || c > '9') && c ^ '-') if((c = getchar()) == EOF) exit(0);
    if(c ^ '-') x = c & 15, k = 1; else x = 0, k = 0;
    while(c = getchar(), c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c & 15);
    return k ? x : -x;
}

const int maxn = 100, mod = 998244353;
char s[10];
int trie[maxn][26], tot;
bool endp[maxn];

void insert(char *s){
    int len = strlen(s), cur = 0;
    for(int i = 0; i < len; i++){
        if(!trie[cur][s[i] - 'a']) trie[cur][s[i] - 'a'] = ++tot;
        cur = trie[cur][s[i] - 'a'];
    }
    endp[cur] = 1;
}

typedef vector<int> vec;
typedef vector<vec> mat;

// 计算矩阵A*矩阵B，元素对mod取模
mat mod_mul(mat &A, mat &B){
    mat C(A.size(), vec(B[0].size()));
    for(int i = 0; i < A.size(); i++){
        for(int k = 0; k < B.size(); k++){
            for(int j = 0; j < B[0].size(); j++){
                C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
            }
        }
    }
    return C;
}

// 计算矩阵A的n次方
mat mod_pow(mat A, LL n){
    mat B(A.size(), vec(A.size()));
    for(int i =0; i < A.size(); i++) B[i][i] = 1;
    while(n > 0){
        if(n & 1) B = mod_mul(B, A);
        A = mod_mul(A, A);
        n >>= 1;
    }
    return B;
}

queue<pii> que;
map<pii, int> mp;
int cnt;
int get_id(pii p){
    if(mp.count(p)) return mp[p];
    mp[p] = cnt++;
    que.push(p);
    return cnt - 1;
}

int main(){
    int n = read(), m = read();
    for(int i = 1; i <= n; i++){
        scanf("%s", s);
        insert(s);
    }
    mat M = mat(170, vec(170));
    get_id(pii(0, 0));
    while(que.size()){
        pii p = que.front(); que.pop();
        int p1 = p.first, p2 = p.second, id = get_id(p);
        for(int i = 0; i < 26; i++){
            int tp1 = trie[p1][i], tp2 = trie[p2][i];
            if(!tp1 || !tp2) continue;
            M[id][get_id(pii(tp1, tp2))]++;
            if(endp[tp1]) M[id][get_id(pii(0, tp2))]++;
            if(endp[tp2]) M[id][get_id(pii(0, tp1))]++;
            if(endp[tp1] && endp[tp2]) M[id][get_id(pii(0, 0))]++;
        }
    }
    /*for(int i = 0; i < 15; i++){
        for(int j = 0; j < 15; j++)
            cout << M[i][j] << ' ';
        cout << endl;
    }*/
    mat ans = mod_pow(M, m);
    cout << ans[0][0] << endl;
    return 0;
}

#include <iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#include<ctime>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<bitset>
#define sqr(x) ((x)*(x))
#define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
#define fd1(i,n) for ((i)=(n);(i)>=1;(i)--)
#define fz0g(i,n) for ((i)=0;(i)<=(n);(i)++)
#define fd0g(i,n) for ((i)=(n);(i)>=0;(i)--)
#define fz0k(i,n) for ((i)=0;(i)<(n);(i)++)
#define fd0k(i,n) for ((i)=(long long)((n)-1);(i)>=0;(i)--)
#define fz(i,x,y) for ((i)=(x);(i)<=(y);(i)++)
#define fd(i,y,x) for ((i)=(y);(i)>=(x);(i)--)
#define fzin fz1(i,n)
#define fzim fz1(i,m)
#define fzjn fz1(j,n)
#define fzjm fz1(j,m)
#define ff(c,itr) for (__typeof((c).begin()) itr=(c).begin();itr!=(c).end();++itr)
#define rdst(st,len){static char ss[len];scanf(" %s",ss);(st)=ss;}
#define incm(x,y) {x=((x)+(y))%mod;}
#define spln(i,n) (i==n?'\n':' ')
#define fac_init(n){fac[0]=fac[1]=inv[1]=fi[0]=fi[1]=1;fz(i,2,n){fac[i]=1ll*fac[i-1]*i%mod;inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;fi[i]=1ll*fi[i-1]*inv[i]%mod;}}
#define fi first
#define se second
#define mk make_pair
using namespace std;
inline void read(int &x)
{
	char c;int f=1;
	while(!isdigit(c=getchar()))if(c=='-')f=-1;
	x=(c&15);while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);
	x*=f;
}
const int mod=998244353;
const long long mod2=1ll*mod*mod;
int n,m,i,j,k,cnt=1,ch[45][26],ed[45];
int a[1005][1005],b[1005][1005];
long long c[1005][1005];
string st;
int id[45][45],cid;
void dfs(int x,int y)
{
	if(x>y){
		id[x][y]=id[y][x];
		return;
	}
	if(id[x][y]) return;
	id[x][y]=++cid;
	if(ed[x]) dfs(1,y);
	if(ed[y]) dfs(x,1);
	int i;
	fz0k(i,26)if(ch[x][i]&&ch[y][i])dfs(ch[x][i],ch[y][i]);
}
int main()
{
	cin>>n>>m;
	while(n--){
		cin>>st;
		int x=1;
		fz0k(i,st.size()){
			if(!ch[x][st[i]-'a']){
				ch[x][st[i]-'a']=++cnt;
			}
			x=ch[x][st[i]-'a'];
		}
		ed[x]++;
	}
	dfs(1,1);
	int x,y;
	fz1(x,cnt)fz1(y,cnt)if(x<=y&&id[x][y]){
		fz0k(i,26)if(ch[x][i]&&ch[y][i]){
			a[id[x][y]][id[ch[x][i]][ch[y][i]]]+=1;
			a[id[x][y]][id[ch[x][i]][1]]+=ed[ch[y][i]];
			a[id[x][y]][id[1][ch[y][i]]]+=ed[ch[x][i]];
			a[id[x][y]][id[1][1]]+=ed[ch[x][i]]*ed[ch[y][i]];
		}
	}
	cerr<<cid<<endl;
//	fz1(x,cnt)fz1(y,cnt)fz1(i,cnt)fz1(j,cnt)if(a[id[x][y]][id[i][j]]){
//		cerr<<x<<' '<<y<<' '<<i<<' '<<j<<' '<<a[id[x][y]][id[i][j]]<<endl;
//	}
	fz1(i,cid) b[i][i]=1;
	while(m){
		if(m&1){
			fz1(i,cid)fz1(j,cid){
				c[i][j]=0;
				fz1(k,cid){
					c[i][j]=(c[i][j]+1ll*a[i][k]*b[k][j]);
					if(c[i][j]>=mod2)c[i][j]-=mod2;
				}
			}
			fz1(i,cid)fz1(j,cid){
				b[i][j]=c[i][j]%mod;
			}
		}
		m/=2;
		fz1(i,cid)fz1(j,cid){
			c[i][j]=0;
			fz1(k,cid){
				c[i][j]=(c[i][j]+1ll*a[i][k]*a[k][j]);
				if(c[i][j]>=mod2)c[i][j]-=mod2;
			}
		}
		fz1(i,cid)fz1(j,cid){
			a[i][j]=c[i][j]%mod;
		}
	}
	cout<<b[id[1][1]][id[1][1]]<<endl;
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
#ifdef local
void debug_out() { cerr << endl; }
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
    cerr << " " << to_string(H);
    debug_out(T...);
}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
typedef long long ll;
#define f(i, l, r) for(int i=l;i<=r;i++)
#define rf(i, r, l) for(int i=r;i>=l;--i)
#define all(x) x.begin(),x.end()
const int N = 2e5+10, mod = 998244353;
ll power(ll a, ll b) {ll res = 1;while (b) {if (b & 1)res = res * a % mod;a = a * a % mod;b >>= 1;}return res;}
ll INV(ll a){return power(a,mod-2);}
mt19937 Rand(123456);
int Range(int l,int r){
    return l+Rand()%(r-l+1);
}

namespace linear_seq {
#define rep(i,a,n) for (int i=a;i<n;i++)
#define VI vector<int>
#define SZ(x) ((int)(x).size())
#define pb push_back
    const int N = 10010;
    ll res[N], base[N], _c[N], _md[N];
    vector<ll> Md;
    void mul(ll* a, ll* b, int k)
    {
        rep(i, 0, k + k) _c[i] = 0;
        rep(i, 0, k) if (a[i]) rep(j, 0, k) _c[i + j] = (_c[i + j] + a[i] * b[j]) % mod;
        for (int i = k + k - 1; i >= k; i--) if (_c[i])
                rep(j, 0, SZ(Md)) _c[i - k + Md[j]] = (_c[i - k + Md[j]] - _c[i] * _md[Md[j]]) % mod;
        rep(i, 0, k) a[i] = _c[i];
    }
    int solve(ll n, VI a, VI b)
    {
        ll ans = 0, pnt = 0;
        int k = SZ(a);
        assert(SZ(a) == SZ(b));
        rep(i, 0, k) _md[k - 1 - i] = -a[i]; _md[k] = 1;
        Md.clear();
        rep(i, 0, k) if (_md[i] != 0) Md.push_back(i);
        rep(i, 0, k) res[i] = base[i] = 0;
        res[0] = 1;
        while ((1ll << pnt) <= n) pnt++;
        for (int p = pnt; p >= 0; p--)
        {
            mul(res, res, k);
            if ((n >> p) & 1)
            {
                for (int i = k - 1; i >= 0; i--) res[i + 1] = res[i]; res[0] = 0;
                rep(j, 0, SZ(Md)) res[Md[j]] = (res[Md[j]] - res[k] * _md[Md[j]]) % mod;
            }
        }
        rep(i, 0, k) ans = (ans + res[i] * b[i]) % mod;
        if (ans < 0) ans += mod;
        return ans;
    }
    VI BM(VI s) {
        VI C(1, 1), B(1, 1);
        int L = 0, m = 1, b = 1;
        rep(n, 0, SZ(s)) {
            ll d = 0;
            rep(i, 0, L + 1) d = (d + (ll)C[i] * s[n - i]) % mod;
            if (d == 0) ++m;
            else if (2 * L <= n) {
                VI T = C;
                ll c = mod - d * power(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                L = n + 1 - L; B = T; b = d; m = 1;
            }
            else {
                ll c = mod - d * power(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                ++m;
            }
        }
        return C;
    }
    int gao(VI a, ll n) {
        VI c = BM(a);
        c.erase(c.begin());
        debug(c.size());
        rep(i, 0, SZ(c)) c[i] = (mod - c[i]) % mod;
        return solve(n, c, VI(a.begin(), a.begin() + SZ(c)));
    }
};
int dp[300][1700];
int mat[1700][1700];
struct Trie {
    int tr[N][26], tot;
    bool key[N];
    void insert(char* s) {
        int u = 0;
        for (int i = 1; s[i];i++) {
            int c = s[i] - 'a';
            if (tr[u][c] == 0)tr[u][c] = ++tot;
            u = tr[u][c];
        }
        key[u]=1;
    }
    int id(int x,int y){
        return y+x*(tot+1);
    }
    void build_mat(int m){
        f(u,0,tot)f(v,0,tot)f(w,0,25){
            if(tr[u][w]&&tr[v][w])mat[id(u,v)][id(tr[u][w],tr[v][w])]=1;
            if(tr[0][w]&&tr[v][w]&&key[u])mat[id(u,v)][id(tr[0][w],tr[v][w])]=1;
            if(tr[0][w]&&tr[u][w]&&key[v])mat[id(u,v)][id(tr[u][w],tr[0][w])]=1;
            if(tr[0][w]&&key[v]&&key[u])mat[id(u,v)][id(tr[0][w],tr[0][w])]=1;
        }
        int k=(tot+1)*(tot+1);

        vector<int> res,valid_id;
        f(i,0,tot)f(j,0,tot)if(key[i]&&key[j])valid_id.push_back(id(i,j));
        dp[0][0]=1;
        f(i,1,60) {
            f(j, 0, k)f(x, 0, k)dp[i][j] = (dp[i][j] + (ll) dp[i - 1][x] * mat[x][j]) % mod;
            ll ans=0;
            for(auto I:valid_id)ans+=dp[i][I];
            res.push_back(ans%mod);
        }
        printf("%lld\n", linear_seq::gao(res, m - 1) % mod);
    }
}T;
char s[N];
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef local
    freopen("../in.txt", "r", stdin);
    clock_t beg=clock();
#endif
    int n,m;cin>>n>>m;
    f(i,1,n){
        cin>>s+1;
        T.insert(s);
    }
    T.build_mat(m);
    debug(clock()-beg);
}

#include <bits/stdc++.h>
using namespace std;
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define loop(i, a) for (int i = 0; i < (a); ++i)
#define cont(i, a) for (int i = 1; i <= (a); ++i)
#define circ(i, a, b) for (int i = (a); i <= (b); ++i)
#define range(i, a, b, c) for (int i = (a); (c) > 0 ? i <= (b) : i >= (b); i += (c))
#define parse(it, x) for (auto &it : (x))
#define pub push_back
#define pob pop_back
#define emb emplace_back
#define mak make_pair
#define mkt make_tuple
typedef long long ll;
typedef long double lf;
const int Inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;

const int jt = 998244353;
void inline add(int &a, int b) { a += b - jt; a += (a >> 31) & jt; }
void inline sub(int &a, int b) { a -= b; a += (a >> 31) & jt; }
void inline mul(int &a, int b) { a = (ll)a * b % jt; }
int inline Add(int a, int b) { return a + b >= jt ? a + b - jt : a + b; }
int inline Sub(int a, int b) { return a - b < 0 ? a - b + jt : a - b; }
int inline Mul(int a, int b) { return (ll)a * b % jt; }

int n, m, t;
char s[9][9];
vector<pair<int, int> > lss;
map<pair<int, int>, int> ids;
int son[44][26], nds;
bool fin[44];
string ss[44];

void dfs(int now) {
	loop(i, 26) if (son[now][i]) {
		ss[son[now][i]] = ss[now] + (char)(i + 'a');
		dfs(son[now][i]);
	}
}

struct Matrix {
	int a[500][500];
	Matrix(int x = 0) {
		loop(i, 500) loop(j, 500) a[i][j] = (i == j ? x : 0);
	}
	Matrix operator * (const Matrix &mat) const {
		static Matrix res;
		loop(i, t) loop(j, t) res.a[i][j] = 0;
		loop(i, t) loop(j, t) loop(k, t) add(res.a[i][k], Mul(a[i][j], mat.a[j][k]));
		return res;
	}
} tr;

Matrix ksmii(Matrix a, int b) {
	Matrix ans(1);
	while (b) {
		if (b & 1) ans = ans * a;
		a = a * a; b >>= 1;
	}
	return ans;
}

int main() {
	scanf("%d%d", &n, &m);
	nds = 1;
	cont(i, n) {
		scanf("%s", s[i]); int len = strlen(s[i]);
		int now = 1;
		loop(j, len) {
			if (!son[now][s[i][j] - 'a']) son[now][s[i][j] - 'a'] = ++nds;
			now = son[now][s[i][j] - 'a'];
		}
		fin[now] = 1;
	}
	dfs(1);
	cont(i, nds) cont(j, nds) {
		if (SZ(ss[j]) > SZ(ss[i])) continue;
		bool can = 1;
		loop(k, SZ(ss[j])) if (ss[j][k] != ss[i][SZ(ss[i]) - SZ(ss[j]) + k]) can = 0;
		if (!can) continue;
		ids[mak(i, j)] = SZ(lss);
		lss.emb(i, j);
	}
	t = SZ(lss);
	loop(i, t) {
		int a, b; tie(a, b) = lss[i];
		loop(c, 26) if (son[a][c] && son[b][c]) {
			++tr.a[i][ids[mak(son[a][c], son[b][c])]];
		}
		loop(j, t) {
			int c, d; tie(c, d) = lss[j];
			if (fin[c]) add(tr.a[i][ids[mak(d, 1)]], tr.a[i][j]);
			if (fin[d]) add(tr.a[i][ids[mak(c, 1)]], tr.a[i][j]);
			if (fin[c] && fin[d]) add(tr.a[i][0], tr.a[i][j]);
		}
	}
	tr = ksmii(tr, m);
	printf("%d\n", tr.a[0][0]);
	return 0;
}

#include<bits/stdc++.h>
#define mk make_pair
using namespace std;
const int N=233;
const int p=998244353;

int read()
{
	int s=0;
	char c=getchar(),lc='+';
	while (c<'0'||'9'<c) lc=c,c=getchar();
	while ('0'<=c&&c<='9') s=s*10+c-'0',c=getchar();
	return lc=='-'?-s:s;
}
void write(int x)
{
	if (x<0) putchar('-'),x=-x;
	if (x<10) putchar(x+'0');
	else write(x/10),putchar(x%10+'0');
}
void print(int x=-1,char c='\n')
{
	write(x);
	putchar(c);
}
void add(int &x,int y){x+=y;if (x>=p) x-=p;}
int cnt,id[50][50],vis[50][50];
struct Matrix{int a[N][N];}tr;
struct Vector{int a[N];}f;
Matrix operator *(const Matrix &a,const Matrix &b)
{
	Matrix ret;
	memset(ret.a,0,sizeof(ret.a));
	for (int i=1;i<=cnt;i++)
	for (int k=1;k<=cnt;k++)
	for (int j=1;j<=cnt;j++)
	add(ret.a[i][j],1LL*a.a[i][k]*b.a[k][j]%p);
	return ret;
}
Vector operator *(const Vector &a,const Matrix &b)
{
	Vector ret;
	memset(ret.a,0,sizeof(ret.a));
	for (int i=1;i<=cnt;i++)
	for (int j=1;j<=cnt;j++)
	add(ret.a[j],1LL*a.a[i]*b.a[i][j]%p);
	return ret;
}
char a[10];
struct trie
{
	int cnt;
	struct node
	{
		int son[26],end,down;
	}t[50];
	void insert(char *a,int len)
	{
		int now=0;
		#define to t[now].son[a[i]-'a']
		for (int i=1;i<=len;i++)
		{
			if (!to) to=++cnt;
			now=to;
		}
		t[now].end=1;
		#undef to
	}
	void ysgs()
	{
		for (int i=0;i<=cnt;i++)
		for (int j=0;j<26;j++) t[i].down|=!!t[i].son[j];
	}
	void dfs(int u,int v)
	{
		if (vis[u][v]) return;
		vis[u][v]=1;
		for (int k=0;k<26;k++)
		if (t[u].son[k]&&t[v].son[k])
		{
			int nu=t[u].son[k],nv=t[v].son[k];
			for (int i=!t[nu].down;i<=t[nu].end;i++)
			for (int j=!t[nv].down;j<=t[nv].end;j++)
			{
				nu=t[u].son[k],nv=t[v].son[k];
				if (i) nu=0; if (j) nv=0;
				dfs(nu,nv);
			}
		}
	}
	void build()
	{
		for (int u=0;u<=cnt;u++)
		for (int v=u;v<=cnt;v++)
		if (id[u][v])
		for (int k=0;k<26;k++)
		if (t[u].son[k]&&t[v].son[k])
		{
			int nu=t[u].son[k],nv=t[v].son[k];
			for (int i=!t[nu].down;i<=t[nu].end;i++)
			for (int j=!t[nv].down;j<=t[nv].end;j++)
			{
				nu=t[u].son[k],nv=t[v].son[k];
				if (i) nu=0; if (j) nv=0;
				tr.a[id[u][v]][id[nu][nv]]=1+(!nu&&!nv&&u!=v);
//				print(id[u][v],' ');
//				print(id[nu][nv],':');
//				print(tr.a[id[u][v]][id[nu][nv]]);
			}
		}
	}
}t;

signed main(signed Goodbye,char *Wangang[])
{
	(void)Goodbye,(void)Wangang;
	int n=read(),m=read();
	for (int i=1;i<=n;i++)
	{
		scanf("%s",a+1);
		t.insert(a,strlen(a+1));
	}
	t.ysgs();
	t.dfs(0,0);
	for (int i=0;i<=t.cnt;i++)
	for (int j=i;j<=t.cnt;j++)
	if (vis[i][j]) id[i][j]=id[j][i]=++cnt;
	t.build();
	f.a[1]=1;
	while (m)
	{
		if (m&1) f=f*tr;
		tr=tr*tr;
		m/=2;
	}
	print(f.a[1]);

	return 0;
}

/* https://csacademy.com/submission/2759503/ (rainboy) */
#include <stdio.h>
#include <string.h>

#define N	8
#define L	5
#define N_	(1 + N * L)
#define N1	(N_ * 2)
#define A	26
#define MD	998244353

int tt[1 + N_][A]; char word[1 + N_];

void dfs(int coef[][L + 1], int s1, int s2, int l) {
	int a;

	if (s1 == 0 || s2 == 0)
		return;
	if (l > 0) {
		if (word[s1])
			coef[s2 - 1 << 1 | 0][l]++;
		if (word[s2])
			coef[s1 - 1 << 1 | 1][l]++;
		if (word[s1] && word[s2])
			coef[0][l]++;
	}
	for (a = 0; a < A; a++)
		dfs(coef, tt[s1][a], tt[s2][a], l + 1);
}

int coef[N1][N1][L + 1];

void apply(int aa[][N1][L], int n) {
	static int bb[N1][N1];
	int i, j, k, l;

	for (i = 0; i < n; i++)
		memset(bb[i], 0, n * sizeof *bb[i]);
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			for (k = 0; k < n; k++)
				for (l = 1; l <= L; l++)
					bb[i][k] = (bb[i][k] + (long long) aa[i][j][l - 1] * coef[j][k][l]) % MD;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			for (l = L - 1; l >= 0; l--)
				aa[i][j][l] = l == 0 ? bb[i][j] : aa[i][j][l - 1];
}

void mult(int aa[][N1][L], int bb[][N1][L], int cc[][N1][L], int n) {
	static int aa_[N1][N1][L], bb_[N1][N1][L + L];
	int i, j, k, l, l1, l2;

	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			memcpy(aa_[i][j], aa[i][j], L * sizeof *aa[i][j]);
	for (l = 0; l < L; l++)
		for (i = 0; i < n; i++)
			for (j = 0; j < n; j++)
				for (k = 0; k < n; k++)
					for (l1 = 1; l + l1 < L; l1++)
						aa_[i][k][l] = (aa_[i][k][l] - (long long) aa_[i][j][l + l1] * coef[j][k][l1]) % MD;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++) {
			memset(bb_[i][j], 0, L * sizeof *bb_[i][j]);
			memcpy(bb_[i][j] + L, bb[i][j], L * sizeof *bb[i][j]);
		}
	for (l = L - 1; l >= 0; l--)
		for (i = 0; i < n; i++)
			for (j = 0; j < n; j++)
				for (k = 0; k < n; k++)
					for (l1 = 1; l1 <= L; l1++)
						bb_[i][k][l] = (bb_[i][k][l] + (long long) coef[i][j][l1] * bb_[j][k][l + l1]) % MD;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			memset(cc[i][j], 0, L * sizeof *cc[i][j]);
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			for (k = 0; k < n; k++)
				for (l1 = 0; l1 < L; l1++)
					for (l2 = L - l1; l1 + l2 - L < L; l2++)
						cc[i][k][l1 + l2 - L] = (cc[i][k][l1 + l2 - L] + (long long) aa_[i][j][l1] * bb_[j][k][l2]) % MD;
}

void power(int pp[][N1][L], int tt[][N1][L], int n, int k) {
	int i, j, l;

	if (k == 0) {
		for (i = 0; i < n; i++)
			for (j = 0; j < n; j++)
				for (l = 0; l < L; l++)
					pp[i][j][l] = i == j && l == 0;
		return;
	}
	power(tt, pp, n, k / 2);
	mult(tt, tt, pp, n);
	if (k & 1)
		apply(pp, n);
	printf("ok %d\n", k);
}

int main() {
	static int pp[N1][N1][L], tt_[N1][N1][L];
	int n, n_, k, i, s;

	scanf("%d%d", &n, &k);
	n_ = 1;
	for (i = 0; i < n; i++) {
		static char cc[L + 1];
		int l, h;

		scanf("%s", cc), l = strlen(cc);
		for (h = 0, s = 1; h < l; h++) {
			int a = cc[h] - 'a';

			if (!tt[s][a])
				tt[s][a] = ++n_;
			s = tt[s][a];
		}
		word[s] = 1;
	}
	for (s = 0; s < n_; s++) {
		dfs(coef[s << 1 | 0], 1, s + 1, 0);
		if (s != 0)
			dfs(coef[s << 1 | 1], s + 1, 1, 0);
	}
	power(pp, tt_, n_ * 2, k);
	if (pp[0][0][0] < 0)
		pp[0][0][0] += MD;
	printf("%d\n", pp[0][0][0]);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

using db = double;
using s64 = long long;
using ld = long double;
using u32 = unsigned int;
using u64 = unsigned long long;

using pii = pair<int, int>;
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)

#define For(i, a, b) for (decay<decltype(b)>::type i = (a), _##i = (b); i <= _##i; ++i)
#define Ford(i, a, b) for (decay<decltype(a)>::type i = (a), _##i = (b); i >= _##i; --i)
#define FOR(i, a, b) for (decay<decltype(b)>::type i = (a), _##i = (b); i < _##i; ++i)
#define FORD(i, a, b) for (decay<decltype(a)>::type i = (a) - 1, _##i = (b); i >= _##i; --i)

#ifdef LOCAL
#define Debug(x...) do { cout << "\033[32;1m" << #x << " -> "; Err(x); } while (0)
void Err() { cout << "\033[39;0m" << endl; }
template<template<typename...> class T, typename t, typename... A>
void Err(T<t> a, A... x) { for (auto v: a) cout << v << ' '; err(x...); }
template<typename T, typename... A>
void Err(T a, A... x) { cout << a << ' '; err(x...); }
#else
#define Debug(...)
#endif

#define all(x) x.begin(), x.end()

const double PI = acos(-1);
const double eps = 1e-7;

const int P = 998244353;
int Add(int x, int y) {return (x += y) >= P ? x - P : x;}
int Dec(int x, int y) {return (x -= y) < 0 ? x + P : x;}
int Mult(int &x, int y) {return x = (s64) x * y % P;}
int add(int &x, int y) {return (x += y) >= P ? x -= P : x;}
int dec(int &x, int y) {return (x -= y) < 0 ? x += P : x;}
int mult(int x, int y) {return (s64) x * y % P;}
int fpw(int x, int k = P - 2) {
	int res = 1;
	for (; k; k >>= 1, x = mult(x, x))
		if (k & 1) res = mult(res, x);
	return res;
}

namespace Solver {
    const char endl = '\n';
	const int MT = 50, K = 26;
	struct Matrix {
		int a[MT * MT][MT * MT], N;
		Matrix() = default;
		Matrix (int n) {memset(a, 0, sizeof a); N = n;}
		Matrix operator * (const Matrix &b) const {
			Matrix res(N);
			FOR (i, 0, N) FOR (k, 0, N) if (a[i][k]) FOR (j, 0, N)
				add(res.a[i][j], mult(a[i][k], b.a[k][j]));
			return res;
		}
	}A, S;
	map<pii, int> f;
	int n, m, tcnt, vcnt, ch[MT][K];
	bool isEnd[MT], vis[MT * MT];
	Matrix calc(Matrix x, int k) {
		Matrix res = Matrix(vcnt);
		FOR (i, 0, vcnt) res.a[i][i] = 1;
		for (; k; k >>= 1, x = x * x)
			if (k & 1) res = res * x;
		return res;
	}
	void main() {
		cin >> n >> m;
		For (i, 1, n) {
			string s;
			cin >> s;
			int u = 0;
			for (auto c : s) {
				if (!ch[u][c - 'a']) ch[u][c - 'a'] = ++tcnt;
				u = ch[u][c - 'a'];
			}
			isEnd[u] = 1;
		}
		auto getIndex = [](const int &x, const int &y) {
			pii u = mp(x, y);
			if (f.find(u) != f.end()) return f[u];
			return f[u] = vcnt++;
		};
		queue<pii> q;
		q.emplace(0, 0);
		vis[getIndex(0, 0)] = 1;
		for (; !q.empty(); q.pop()) {
			auto [x, y] = q.front();
			int u = getIndex(x, y);
			vis[u] = 1;
			FOR (i, 0, K)
				if (ch[x][i] && ch[y][i]) {
					int nx = ch[x][i], ny = ch[y][i];
					int v = getIndex(nx, ny);
					A.a[u][v] = 1;
					if (!vis[v]) q.emplace(nx, ny);
					if (isEnd[nx]) {
						int nv = getIndex(0, ny);
						A.a[u][nv] = 1;
						if (!vis[nv]) q.emplace(0, ny);
					}
					if (isEnd[ny]) {
						int nv = getIndex(nx, 0);
						A.a[u][nv] = 1;
						if (!vis[nv]) q.emplace(nx, 0);
					}
					if (isEnd[nx] && isEnd[ny])
						A.a[u][0] = 1;
				}
		}
		S.N = A.N = vcnt;
		S.a[0][0] = 1;
		cout << (S * calc(A, m)).a[0][0] << endl;
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int T = 1;
	//cin >> T;
	For(_t, 1, T) {
		// cout << "Case #" << _t << ": ";
		// cout << endl;
		Solver::main();
	}
	return 0;
}

#include<bits/stdc++.h>
#define pb push_back
#define x first
#define y second
#define pdd pair<double,double>
#define pii pair<int,int>
#define pll pair<LL,LL>
#define mp make_pair
#define LL long long
#define ULL unsigned long long
#define sqr(x) ((x)*(x))
#define pi acosl(-1)
#define MEM(x) memset(x,0,sizeof(x))
#define MEMS(x) memset(x,-1,sizeof(x))
using namespace std;
const int mod=998244353;
struct matrix{
    LL a[355][355];
    int n;
    matrix(){
        MEM(a);
    }
};
int num[40][40];
int aa[1005][1005];
matrix operator*(const matrix &a,const matrix &b){
    matrix c;
    c.n=a.n;
    for(int i = 0;i<c.n;i++){
        for(int k =0;k<c.n;k++){
            if(a.a[i][k]){
                for(int j=0;j<c.n;j++){
                    if(b.a[k][j])
                        c.a[i][j]+=a.a[i][k]*b.a[k][j]%mod;
                }
            }
           // c.a[i][j]%=mod;
        }
    }
    for(int i = 0;i<c.n;i++){
        for(int j=0;j<c.n;j++){
            c.a[i][j]%=mod;
        }
    }
    return c;
}
matrix f_pow(matrix a,int b){
    matrix res,tmp=a;
    res.n=a.n;
    for(int i = 0;i<res.n;i++)res.a[i][i]=1;
    while(b){
        if(b&1)res=res*tmp;
        tmp=tmp*tmp;
        b>>=1;
    }
    return res;
}
void solve(){
    int n,m;
    scanf("%d %d",&n,&m);
    char c[8][20];
    int val[8][20];
    pii rval[50];
    int index=1;
    for(int i = 0;i<n;i++){
        scanf("%s",c[i]);
        for(int j=0;c[i][j]!=0;j++){
            if(c[i][j+1]==0)val[i][j]=0;
            else rval[index]=mp(i,j),val[i][j]=index++;
        }
    }
    MEMS(num);
    queue<pii> q;
    q.push(mp(0,0));
    num[0][0]=0;
    index=1;
    //int index=1;
    int ok[1777];
    MEM(ok);
    while(!q.empty()){
        pii p=q.front();
        q.pop();
        for(int i = 0;i<26;i++){
            if(p.x==0){
                if(p.y==0){
                    for(int j = 0;j<n;j++){
                        if(c[j][0]==i+'a'){
                            for(int k = 0;k<n;k++){
                                if(c[k][0]==i+'a'){
                                    int a=val[j][0],b=val[k][0];
                                    if(num[a][b]==-1)num[a][b]=index++,q.push(mp(a,b));
                                    aa[num[p.x][p.y]][num[a][b]]++;
                                    ok[num[p.x][p.y]]=1;
                                }
                            }
                        }
                    }
                }
                else{
                    pii p1=rval[p.y];
                    if(c[p1.x][p1.y+1]==i+'a'){
                        for(int j = 0;j<n;j++){
                            if(c[j][0]==i+'a'){
                                int a=val[j][0],b=val[p1.x][p1.y+1];
                                if(num[a][b]==-1)num[a][b]=index++,q.push(mp(a,b));
                                aa[num[p.x][p.y]][num[a][b]]++;
                                ok[num[p.x][p.y]]=1;
                            }
                        }
                    }
                }
            }
            else if(p.y==0){
                pii p1=rval[p.x];
                if(c[p1.x][p1.y+1]==i+'a'){
                    for(int j = 0;j<n;j++){
                        if(c[j][0]==i+'a'){
                            int a=val[p1.x][p1.y+1],b=val[j][0];
                            if(num[a][b]==-1)num[a][b]=index++,q.push(mp(a,b));
                            aa[num[p.x][p.y]][num[a][b]]++;
                            ok[num[p.x][p.y]]=1;
                        }
                    }
                }
            }
            else{
                pii p1=rval[p.x],p2=rval[p.y];
                if(c[p1.x][p1.y+1]==i+'a'&&c[p2.x][p2.y+1]==i+'a'){
                    int a=val[p1.x][p1.y+1],b=val[p2.x][p2.y+1];
                    if(num[a][b]==-1)num[a][b]=index++,q.push(mp(a,b));
                    aa[num[p.x][p.y]][num[a][b]]++;
                    ok[num[p.x][p.y]]=1;
                }
            }
        }
    }
    int val2[1777];
    MEM(val2);
    int now=0;
    for(int i = 0;i<index;i++){
        if(ok[i])val2[i]=now++;
    }
    printf("%d %d\n",index,now);
    matrix a;
    a.n=now;
    for(int i = 0;i<index;i++){
        for(int j =0;j<index;j++){
            if(ok[i]&&ok[j])
            a.a[val2[i]][val2[j]]=aa[i][j];
        }
    }
    a=f_pow(a,m);
    printf("%lld\n",a.a[0][0]);
}
int main(){
    int t=1;
    //scanf("%d",&t);
    //for(int i = 2)
    while(t--){
        solve();
    }
}

#include <bits/stdc++.h>
using namespace std;
#define fore(i, a, b) for(int i = a; i <= b; i++)
#define Fore(i, a, b) for(int i = a; i < b; i++)
#define pii pair<int, int>
#define fi first
#define se second
#define MP make_pair
#define EP emplace_back
#define li long long

const int MAXN = 200, mod = 998244353;

inline int input(){
    char c = getchar(); int o; bool f = 0;
    while(c > 57 || c < 48)
        f |= (c == '-'), c = getchar();
    for(o = 0; c > 47 && c < 58; c = getchar())
        o = (o << 1)+(o << 3)+(c - 48);
    return f ? -o : o;
}

int cnt = 1, ch[MAXN][30], mark[MAXN][MAXN];
bool mk[MAXN], vis[MAXN][MAXN];

struct mat{
    int v[201][201];
    mat(){memset(v, 0, sizeof(v));}
    mat operator * (const mat &B)const{
        mat ret;
        fore(i, 0, 200)
        fore(j, 0, 200)
            fore(mid, 0, 200)
                ret.v[i][j] = (ret.v[i][j] + 1LL * v[i][mid] * B.v[mid][j] % mod) % mod;
        return ret;
    }
}B;

mat KSM(mat A, int t){
    mat ret = A; t--;
    while(t){
        if(t & 1) ret = ret * A;
        t >>= 1;
        A = A * A;
    }
    return ret;
}

pii Q[20000];

void Insert(string &s){
    int rt = 1;
    Fore(i, 0, s.length()){
        int c = s[i] - 'a';
        if(!ch[rt][c]) ch[rt][c] = ++cnt;
        rt = ch[rt][c];
    }
    mk[rt] = 1;
}

void Bfs(){
    cnt = 0;
    int he = 1, ta = 0;
    Q[++ta] = MP(1, 1);
    vis[1][1] = 1; mark[1][1] = 0;
    while(he <= ta){
        pii np = Q[he++];
        int x = np.fi, y = np.se;
        Fore(c, 0, 26)
            if(ch[x][c] && ch[y][c]){
                int cx = ch[x][c], cy = ch[y][c];
                if(!vis[cx][cy])
                    vis[cx][cy] = 1,
                    Q[++ta] = MP(cx, cy),
                    mark[cx][cy] = ++cnt;
                B.v[mark[x][y]][mark[cx][cy]] = 1;
                if(mk[cx]){
                    if(!vis[1][cy])
                        vis[1][cy] = 1,
                        Q[++ta] = MP(1, cy),
                        mark[1][cy] = ++cnt;
                    B.v[mark[x][y]][mark[1][cy]] = 1;
                }
                if(mk[cy]){
                    if(!vis[cx][1])
                        vis[cx][1] = 1,
                        Q[++ta] = MP(cx, 1),
                        mark[cx][1] = ++cnt;
                    B.v[mark[x][y]][mark[cx][1]] = 1;
                }
                if(mk[cx] && mk[cy])
                    B.v[mark[x][y]][0] = 1;
            }
    }
}

int main(){
    int n = input(), m = input();
    string s;
    fore(i, 1, n){
        cin >> s;
        Insert(s);
    }
    Bfs();
    mat res = KSM(B, m);
    printf("%d", res.v[0][0]);
}

#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <ctype.h>
#include <deque>
#include <cstring>
#include <set>
#include <bitset>
#include <map>
#include <chrono>
#include <random>
#include <unordered_map>
#include <stdio.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef std::vector<int> vi;
typedef std::vector<bool> vb;
typedef std::vector<string> vs;
typedef std::vector<double> vd;
typedef std::vector<long long> vll;
typedef std::vector<std::vector<int> > vvi;
typedef vector<vll> vvll;
typedef std::vector<std::pair<int, int> > vpi;
typedef vector<vpi> vvpi;
typedef std::pair<int, int> pi;
typedef std::pair<ll, ll> pll;
typedef std::vector<pll> vpll;

const long long mod = 998244353 ;
const unsigned gen_seed = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937_64 gen(gen_seed);

#define all(c) (c).begin(),(c).end()
#define srt(c) sort(all(c))
#define srtrev(c) sort(all(c)); reverse(all(c))
#define forn(i, a, b) for(int i = a; i < b; i++)
#define read(x) scanf("%d", &x)
#define readv(x, n) vi x(n); forn(i,0,n) scanf("%d", &x[i])

#define pb push_back
#define mp make_pair
vs a;
int valid[9][9][5][5];
int k;

vvll mul(const vvll & x, const vvll & y) {
    vvll res(k, vll(k, 0));
    forn(i,0,k) forn(j,0,k) {
        forn(p,0,k) res[i][j] += x[i][p] * y[p][j] % mod;
        res[i][j] %= mod;
    }
    return res;
}

vll mulv(const vvll & x, const vll & y) {
    vll res(k,0);
    forn(i,0,k) {
        forn(p,0,k) res[i] += x[i][p] * y[p] % mod;
        res[i] %= mod;
    }
    return res;
}

vvll mpow(vvll & x, int k) {
    if(k == 1) return x;
    vvll u = mpow(x, k/2);
    vvll res = mul(u, u);
    if(k%2) res = mul(res, x);
    return res;
}

int main()
{
#ifdef LOCAL
    freopen("input.txt", "rt", stdin);
    freopen("output.txt", "wt", stdout);
#endif
    int n,m;
    scanf("%d %d\n", &n, &m);
    a.pb(string(1,'#'));
    char c[100];
    forn(i,0,n) {
        scanf("%s", c);
        a.pb(string(c));
    }
    forn(i,1,n+1) {
        forn(j,1,n+1) {
            forn(p1,0,a[i].size()) {
                forn(p2,0,a[j].size()) {
//                    if(p1+1 == a[i].size() && p2+1==a[j].size()) continue;
                    int can = 1;
                    for(int k = -4; k<=4; k++) {
                        if(p1+k>=0 && p1+k<a[i].size() && p2+k>=0 && p2+k<a[j].size() && a[i][p1+k] != a[j][p2+k]) can = 0;
                    }
                    if(can) {
                        valid[i][j][p1][p2] = 1;
//                        if(p1 + 1 != a[i].size() && p2 + 1 != a[j].size()) valid[i][j][p1][p2] = 1;
//                        else if(p1+1==a[i].size()) {
//                            valid[0][j][0][p2] = 1;
//                        }
//                        else if(p2+1==a[j].size()) {
//                            valid[i][0][p1][0] = 1;
//                        }
                    }
                }
            }
        }
    }
    vvi state;
    state.pb(vi(4,0));
    forn(i,0,n+1)
        forn(j,0,n+1)
            forn(p1,0,a[i].size())
                forn(p2,0,a[j].size())
                    if(valid[i][j][p1][p2]) state.pb(vi({i,j,p1,p2}));
    map<vi, int> code;
    forn(i,0,state.size()) code[state[i]] = i;
    k = state.size();
//    vector<set<int>> g(k);
    vvll mat(k, vll(k, 0));
    forn(f,0,k) {
        int i = state[f][0];
        int j = state[f][1];
        int p1 = state[f][2];
        int p2 = state[f][3];
        p1++;
        p2++;
        if(p1 == a[i].size()) {
            p1 = 0;
            i = 0;
        }
        if(p2 == a[j].size()) {
            p2 = 0;
            j = 0;
        }
        if (i!=0 && j!=0) {
//            g[f].insert(code[vi({i,j,p1,p2})]);
            mat[code[vi({i,j,p1,p2})]][f]++;
        }
        else if(i==0 && j==0) {
            forn(i2,1,n+1) forn(j2,1,n+1) {
                int can = 1;
                int pt = 0;
                while(pt<a[i2].size() && pt<a[j2].size()) {
                    if(a[i2][pt] != a[j2][pt]) can = 0;
                    pt++;
                }
                if(can) {
                    int p12 = 0;
                    int p22 = 0;
                    int i3 = i2;
                    int j3 = j2;
//                    g[f].insert(code[vi({i3,j3,p12,p22})]);
                    mat[code[vi({i3,j3,p12,p22})]][f]++;
                }
            }
        }
        else if(i == 0) {
            forn(i2,1,n+1) {
                int can = 1;
                int pt = 0;
                while(pt<a[i2].size() && p2+pt < a[j].size()) {
                    if(a[i2][pt] != a[j][p2+pt]) can = 0;
                    pt++;
                }
                if(can) {
                    int i3 = i2;
                    int j3 = j;
                    int p12 = 0;
                    int p22 = p2;
//                    g[f].insert(code[vi({i3,j3,p12,p22})]);
                    mat[code[vi({i3,j3,p12,p22})]][f]++;
                }
            }
        }
        else if(j == 0) {
            forn(j2,1,n+1) {
                int can = 1;
                int pt = 0;
                while(pt<a[j2].size() && p1+pt < a[i].size()) {
                    if(a[j2][pt] != a[i][p1+pt]) can = 0;
                    pt++;
                }
                if(can) {
                    int i3 = i;
                    int j3 = j2;
                    int p12 = p1;
                    int p22 = 0;
//                    g[f].insert(code[vi({i3,j3,p12,p22})]);
                    mat[code[vi({i3,j3,p12,p22})]][f]++;
                }
            }
        }
    }

//    forn(i,0,k) for(auto x : g[i]) mat[x][i] = 1;
    vvi g(k);
    forn(i,0,k) forn(j,0,k) if(mat[i][j] > 0) g[j].pb(i);
    vi vis(k, 0);
    vi q;
    q.pb(0);
    vis[0] = 1;
    while(!q.empty()) {
        int v = q.back();
        q.pop_back();
        for(auto u : g[v]) if(vis[u] == 0) {
            vis[u] = 1;
            q.pb(u);
        }
    }
    vi comp;
    forn(i,0,k) if(vis[i]) comp.pb(i);
    int kwas = k;
    k = comp.size();
    vvll compmat(k, vll(k, 0));
    forn(i,0,k) forn(j,0,k) compmat[i][j] = mat[comp[i]][comp[j]];
    vvll res = mpow(mat, m);
    vll d(k,0);
    d[0] = 1;
    vll ans = mulv(res, d);
    ll fin = 0;
    forn(ff,0,k) {
        int f = comp[ff];
        int i = state[f][0];
        int j = state[f][1];
        int p1 = state[f][2];
        int p2 = state[f][3];
        if(p1+1 == a[i].size()) {
            p1 = 0;
            i = 0;
        }
        if(p2+1 == a[j].size()) {
            p2 = 0;
            j = 0;
        }
        if(i == 0 && j == 0) fin += ans[f];
    }
    cout<<fin%mod;

}

// Problem: F. Chainword
// Contest: Codeforces - Educational Codeforces Round 107 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1511/problem/F
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define ll long long
#define pb push_back
#define f first
#define s second
#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL)
#define D(x) cerr << #x << " is " << (x) << "\n";
#define ld long double
#define li __int128

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>; ///find_by_order(),order_of_key()
template<int D, typename T>struct vec : public vector<vec<D - 1, T>> {template<typename... Args>vec(int n = 0, Args... args) : vector<vec<D - 1, T>>(n, vec<D - 1, T>(args...)) {}};
template<typename T>struct vec<1, T> : public vector<T> {vec(int n = 0, T val = T()) : vector<T>(n, val) {}};
template<class T1,class T2> ostream& operator<<(ostream& os, const pair<T1,T2>& a) { os << '{' << a.f << ", " << a.s << '}'; return os; }
template<class T> ostream& operator<<(ostream& os, const vector<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const deque<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T,greater<T> >& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T,greater<T> >& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> ostream& operator<<(ostream& os, const map<T1,T2>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> istream& operator>>(istream& is,pair<T1,T2>& a) {is>>a.f>>a.s;return is;}
template<class T> istream& operator>>(istream& is,vector<T>& a) {for(auto &p:a)is>>p;return is;}
int ri(){int x;scanf("%i",&x);return x;}
void rd(int&x){scanf("%i",&x);}
void rd(long long&x){scanf("%lld",&x);}
void rd(double&x){scanf("%lf",&x);}
void rd(long double&x){scanf("%Lf",&x);}
void rd(string&x){cin>>x;}
void rd(char*x){scanf("%s",x);}
template<typename T1,typename T2>void rd(pair<T1,T2>&x){rd(x.first);rd(x.second);}
template<typename T>void rd(vector<T>&x){for(T&p:x)rd(p);}
template<typename C,typename...T>void rd(C&a,T&...args){rd(a);rd(args...);}
//istream& operator>>(istream& is,__int128& a){string s;is>>s;a=0;int i=0;bool neg=false;if(s[0]=='-')neg=true,i++;for(;i<s.size();i++)a=a*10+s[i]-'0';if(neg)a*=-1;return is;}
//ostream& operator<<(ostream& os,__int128 a){bool neg=false;if(a<0)neg=true,a*=-1;ll high=(a/(__int128)1e18);ll low=(a-(__int128)1e18*high);string res;if(neg)res+='-';if(high>0){res+=to_string(high);string temp=to_string(low);res+=string(18-temp.size(),'0');res+=temp;}else res+=to_string(low);os<<res;return os;}

const int mod=998244353;
int add(int a,int b){
    a+=b;
    if(a>=mod)
        a-=mod;
    return a;
}
int sub(int a,int b){
    a-=b;
    if(a<0)
        a+=mod;
    return a;
}
int mul(int a,int b){
    return (long long)a*b%mod;
}
int pwrmod(int x,int k){
    int ans=1;
    for(;k;k>>=1,x=mul(x,x))
        if(k&1)
            ans=mul(ans,x);
    return ans;
}

const int N=41,L=26;
vector<int> nxt[N][L];
bool kr[N];
bool pref(string a,string b){
	if(a.size()<b.size())
		return pref(b,a);
	return a.substr(0,b.size())==b;
}
vector<vector<int>> mul(vector<vector<int>> a,vector<vector<int>> b){
	int n=a.size(),m=b[0].size(),l=a[0].size();
	assert(a[0].size()==b.size());
	vector<vector<int>> sol(n,vector<int>(m,0));
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			for(int k=0;k<l;k++)
				sol[i][j]=add(sol[i][j],mul(a[i][k],b[k][j]));
	return sol;
}
int main()
{
	int n=ri(),m=ri();
	vector<string> s(n);
	rd(s);
	map<string,int> done;
	int ind=0;
	vector<string> pre;

	done[""]=ind++;pre.pb("");

	for(int i=0;i<n;i++){
		string tr;
		for(int j=0;j<s[i].size();j++){
			tr+=s[i][j];
			if(done.find(tr)==done.end()){
				done[tr]=ind++;
				pre.pb(tr);
			}
			if(j==s[i].size()-1){
				kr[done[tr]]=1;
			}
		}
	}
	for(auto p:done){
		string tr=p.f;
		int i=p.s;
		for(int j=0;j<26;j++){
			char c='a'+j;
			string novi=tr+c,o;
			o+=c;
			if(done.find(novi)!=done.end())
				nxt[i][j].pb(done[novi]);
			if(kr[i]&&done.find(o)!=done.end())
				nxt[i][j].pb(done[o]);
		}
	}
	vector<pair<int,int>> pr;
	map<pair<int,int>,int> koji;
	for(int i=0;i<ind;i++)
		for(int j=0;j<ind;j++)
			if(pref(pre[i],pre[j])){
				pr.pb({i,j});
				koji[{i,j}]=pr.size()-1;
			}
	int L=pr.size();
	vector<vector<int>> mulMat(L,vector<int>(L,0));
	for(int k=0;k<L;k++){
		int i=pr[k].f,j=pr[k].s;
		for(int l=0;l<26;l++){
			for(auto p:nxt[i][l])
				for(auto d:nxt[j][l]){
					int sl=koji[{p,d}];
					mulMat[k][sl]=1;
				}
		}
	}
	vector<vector<int>> begMat(1,vector<int>(L,0));
	begMat[0][0]=1;
	for(;m;m>>=1,mulMat=mul(mulMat,mulMat))
		if(m&1)
			begMat=mul(begMat,mulMat);
	int sol=0;
	for(int k=0;k<L;k++){
		int i=pr[k].f,j=pr[k].s;
		if(kr[i]&&kr[j])
			sol=add(sol,begMat[0][k]);
	}
	printf("%i\n",sol);
	return 0;
}

/*
 *   ##   #####   ####      ####  #    #  ####
 *  #  #  #    # #    #    #    # #    # #    #
 * #    # #####  #         #    # #    # #    #
 * ###### #    # #         #    # # ## # #    #
 * #    # #    # #    #    #    # ##  ## #    #
 * #    # #####   ####      ####  #    #  ####
 */
#include <bits/stdc++.h>
using namespace std;
#define lli long long int
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define pii pair <int, int>
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define info() cout << __PRETTY_FUNCTION__ << ": " << __LINE__ << endl
void abc() {cout << endl;}
template <typename T, typename ...U> void abc(T a, U ...b) {
    cout << a << ' ', abc(b...);
}
template <typename T> void printv(T l, T r) {
    for (; l != r; ++l) cout << *l << " \n"[l + 1 == r];
}
template <typename A, typename B> istream& operator >> (istream& o, pair<A, B> &a) {
    return o >> a.X >> a.Y;
}
template <typename A, typename B> ostream& operator << (ostream& o, pair<A, B> a) {
    return o << '(' << a.X << ", " << a.Y << ')';
}
template <typename T> ostream& operator << (ostream& o, vector<T> a) {
    bool is = false;
    if (a.empty()) return o << "{}";
    for (T i : a) {o << (is ? ' ' : '{'), is = true, o << i;}
    return o << '}';
}
template <typename T> struct vv : vector <vector <T>> {
    vv(int n, int m, T v) : vector <vector <T>> (n, vector <T>(m, v)) {}
    vv() {}
};
template <typename T> struct vvv : vector <vv <T>> {
    vvv(int n, int m, int k, T v) : vector <vv <T>> (n, vv <T>(m, k, v)) {}
    vvv() {}
};
#ifdef Doludu
#define test(args...) abc("[" + string(#args) + "]", args)
#define owo freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout);
#else
#define test(args...) void(0)
#define owo ios::sync_with_stdio(false); cin.tie(0)
#endif
const int mod = 998244353, N = 300001, logN = 19, K = 1 << 9;

struct mat {
    int n;
    long long mod2;
    vector <vector <long long>> val;
    mat (int _n, int _mode = 0) : n(_n), mod2(1ll * mod * mod) {
        // mode 1 -> I, other -> O
        val.assign(n, vector<long long>(n, 0));
        if (_mode == 1) {
            for (int i = 0; i < n; ++i) val[i][i] = 1;
        }
    }
    mat (const mat& M) : n(M.n), mod2(1ll * mod * mod) {
        val.assign(n, vector<long long>(n, 0));
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                val[i][j] = M.val[i][j];
            }
        }
    }
    mat (vector <vector <long long>> v) : n(v.size()), mod2(1ll * mod * mod), val(v) {}
    mat operator + (const mat& o) {
        mat ans(o);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                ans.val[i][j] += val[i][j];
                if (ans.val[i][j] >= mod) ans.val[i][j] -= mod;
            }
        }
        return ans;
    }
    mat operator * (const mat& o) {
        mat ans(n, 0);
        for (int i = 0; i < n; ++i) {
            for (int k = 0; k < n; ++k) {
                for (int j = 0; j < n; ++j) {
                    ans.val[i][j] += val[i][k] * o.val[k][j];
                    if (ans.val[i][j] >= mod2) ans.val[i][j] -= mod2;
                }
            }
        }
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                ans.val[i][j] %= mod;
            }
        }
        return ans;
    }
    mat operator ^ (long long k) {
        mat ans(n, 1), a(*this);
        for (; k; k >>= 1, a = a * a) {
            if (k & 1) ans = ans * a;
        }
        return ans;
    }
};

int main() {
    owo;
    int n, m;
    cin >> n >> m;
    vector <string> pre;
    vector <int> fin;
    pre.pb(""), fin.pb(0);
    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 1; j <= s.length(); ++j) {
            if (find(all(pre), s.substr(0, j)) == pre.end()) {
                pre.pb(s.substr(0, j)), fin.pb(0);
            }
        }
        fin[find(all(pre), s) - pre.begin()] = 1;
    }
    vector <pii> dim;
    for (int i = 0; i < pre.size(); ++i) {
        for (int j = i; j < pre.size(); ++j) {
            string s = pre[i], t = pre[j];
            if (s.length() > t.length())
                swap(s, t);
            if (t.substr(t.length() - s.length()) == s) {
                dim.eb(i, j);
            }
        }
    }
    auto append = [&](int i, char c) {
        if (find(all(pre), pre[i] + c) != pre.end()) {
            return find(all(pre), pre[i] + c) - pre.begin();
        }
        return -1;
    };
    n = dim.size();
    vv <long long> a(n, n, 0);
    function<void(int, int, int)> add_ma = [&](int i, int l, int r) {
        if (find(all(dim), mp(l, r)) != dim.end())
            a[i][find(all(dim), mp(l, r)) - dim.begin()]++;
    };
    for (int i = 0; i < n; ++i) {
        for (char c = 'a'; c <= 'z'; ++c) {
            int l, r;
            tie(l, r) = dim[i];
            l = append(l, c), r = append(r, c);
            if (l == -1 || r == -1)
                continue;
            if (l > r)
                swap(l, r);
            add_ma(i, l, r);
            if (fin[l])
                add_ma(i, 0, r);
            if (fin[r])
                add_ma(i, l, 0);
            if (fin[l] && fin[r])
                add_ma(i, 0, 0);
        }
    }
    mat M(a);
    M = M ^ m;
    cout << M.val[0][0] << endl;
}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll MOD = 998244353;
const int LEN = 26;
char c[100];
int n, m;
int id[300][300], all = 0;

struct Matrix {
    ll key[300][300];
    int n;

    void clear() {
        for (int i = 0; i < 300; i++)
            for (int j = 0; j < 300; j++)
                key[i][j] = 0;
    }

    void init(int _n) {
        n = _n;
        clear();
        for (int i = 1; i <= n; i++)
            key[i][i] = 1;
    }

    Matrix operator *(Matrix &b) {
        Matrix now;
        now.clear();
        now.n = this->n;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                for (int k = 1; k <= n; k++) {
                    (now.key[i][j] += this->key[i][k] * b.key[k][j]) % MOD;
                }
        return now;
    }

    void out() {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++)
                printf("%d ", key[i][j]);
            puts("");
        }
    }
} mat;

struct Trie {
    int ch[100][30], root, all, key[1000];

    int newnode() {
        for (int i = 0; i < LEN; i++)
            ch[all][i] = 0;
        key[all] = 0;
        all++;
        return all - 1;
    }

    void init() {
        all = 0;
        root = newnode();
    }

    void insert(char *c) {
        int len = strlen(c);
        int now = root;
        for (int i = 0; i < len; i++) {
            if (ch[now][i] == 0)
                ch[now][i] = newnode();
            now = ch[now][i];
        }
        key[now]++;
    }
} tr;

Matrix P(Matrix x, int y) {
    Matrix ans;
    ans.init(x.n);
    for (; y; y >>= 1) {
        if (y % 2)
            ans = ans * x;
        x = x * x;
    }
    return ans;
}

void dfs(int x, int y) {
    if (id[x][y] != 0)
        return;
    id[x][y] = ++all;
    for (int i = 0; i < LEN; i++)
        if (tr.ch[x][i] > 0 && tr.ch[y][i] > 0) {
            int nowx = tr.ch[x][i], nowy = tr.ch[y][i];
            dfs(0, nowy);
            dfs(nowx, 0);
            dfs(nowx, nowy);
            if (tr.key[nowx]) {
                mat.key[id[x][y]][id[0][nowy]]++;
            }
            if (tr.key[nowy]) {
                mat.key[id[x][y]][id[nowx][0]]++;
            }
            if (tr.key[nowx] && tr.key[nowy]) {
                mat.key[id[x][y]][1]++;
            }
            mat.key[id[x][y]][id[nowx][nowy]]++;
        }
}

int main() {
    scanf("%d%d", &n, &m);
    tr.init();
    for (int i = 1; i <= n; i++) {
        scanf(" %s", c);
        tr.insert(c);
    }
    dfs(0, 0);
    mat.n = all;
    mat = P(mat, m);
    printf("%lld\n", mat.key[1][1]);
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#ifdef local
void debug_out() { cerr << endl; }
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
    cerr << " " << to_string(H);
    debug_out(T...);
}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
typedef long long ll;
#define f(i, l, r) for(int i=l;i<=r;i++)
#define rf(i, r, l) for(int i=r;i>=l;--i)
#define all(x) x.begin(),x.end()
const int N = 2e5+10, mod = 998244353;
ll power(ll a, ll b) {ll res = 1;while (b) {if (b & 1)res = res * a % mod;a = a * a % mod;b >>= 1;}return res;}
ll INV(ll a){return power(a,mod-2);}
mt19937 Rand(123456);
int Range(int l,int r){
    return l+Rand()%(r-l+1);
}

namespace linear_seq {
#define rep(i,a,n) for (int i=a;i<n;i++)
#define VI vector<int>
#define SZ(x) ((int)(x).size())
#define pb push_back
    const int N = 10010;
    ll res[N], base[N], _c[N], _md[N];
    vector<ll> Md;
    void mul(ll* a, ll* b, int k)
    {
        rep(i, 0, k + k) _c[i] = 0;
        rep(i, 0, k) if (a[i]) rep(j, 0, k) _c[i + j] = (_c[i + j] + a[i] * b[j]) % mod;
        for (int i = k + k - 1; i >= k; i--) if (_c[i])
                rep(j, 0, SZ(Md)) _c[i - k + Md[j]] = (_c[i - k + Md[j]] - _c[i] * _md[Md[j]]) % mod;
        rep(i, 0, k) a[i] = _c[i];
    }
    int solve(ll n, VI a, VI b)
    {
        ll ans = 0, pnt = 0;
        int k = SZ(a);
        assert(SZ(a) == SZ(b));
        rep(i, 0, k) _md[k - 1 - i] = -a[i]; _md[k] = 1;
        Md.clear();
        rep(i, 0, k) if (_md[i] != 0) Md.push_back(i);
        rep(i, 0, k) res[i] = base[i] = 0;
        res[0] = 1;
        while ((1ll << pnt) <= n) pnt++;
        for (int p = pnt; p >= 0; p--)
        {
            mul(res, res, k);
            if ((n >> p) & 1)
            {
                for (int i = k - 1; i >= 0; i--) res[i + 1] = res[i]; res[0] = 0;
                rep(j, 0, SZ(Md)) res[Md[j]] = (res[Md[j]] - res[k] * _md[Md[j]]) % mod;
            }
        }
        rep(i, 0, k) ans = (ans + res[i] * b[i]) % mod;
        if (ans < 0) ans += mod;
        return ans;
    }
    VI BM(VI s) {
        VI C(1, 1), B(1, 1);
        int L = 0, m = 1, b = 1;
        rep(n, 0, SZ(s)) {
            ll d = 0;
            rep(i, 0, L + 1) d = (d + (ll)C[i] * s[n - i]) % mod;
            if (d == 0) ++m;
            else if (2 * L <= n) {
                VI T = C;
                ll c = mod - d * power(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                L = n + 1 - L; B = T; b = d; m = 1;
            }
            else {
                ll c = mod - d * power(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                ++m;
            }
        }
        return C;
    }
    int gao(VI a, ll n) {
        VI c = BM(a);
        c.erase(c.begin());
        debug(c.size());
        rep(i, 0, SZ(c)) c[i] = (mod - c[i]) % mod;
        return solve(n, c, VI(a.begin(), a.begin() + SZ(c)));
    }
};
int dp[50][1700];
int mat[1700][1700];
struct Trie {
    int tr[N][26], tot;
    bool key[N];
    void insert(char* s) {
        int u = 0;
        for (int i = 1; s[i];i++) {
            int c = s[i] - 'a';
            if (tr[u][c] == 0)tr[u][c] = ++tot;
            u = tr[u][c];
        }
        key[u]=1;
    }
    int id(int x,int y){
        return y+x*(tot+1);
    }
    void build_mat(int m){
        f(u,0,tot)f(v,0,tot)f(w,0,25){
            if(tr[u][w]&&tr[v][w])mat[id(u,v)][id(tr[u][w],tr[v][w])]=1;
            if(tr[0][w]&&tr[v][w]&&key[u])mat[id(u,v)][id(tr[0][w],tr[v][w])]=1;
            if(tr[0][w]&&tr[u][w]&&key[v])mat[id(u,v)][id(tr[u][w],tr[0][w])]=1;
            if(tr[0][w]&&key[v]&&key[u])mat[id(u,v)][id(tr[0][w],tr[0][w])]=1;
        }
        int k=(tot+1)*(tot+1);

        vector<int> res,valid_id;
        f(i,0,tot)f(j,0,tot)if(key[i]&&key[j])valid_id.push_back(id(i,j));
        dp[0][0]=1;
        f(i,1,40) {
            f(j, 0, k)f(x, 0, k)dp[i][j] = (dp[i][j] + (ll) dp[i - 1][x] * mat[x][j]) % mod;
            ll ans=0;
            for(auto I:valid_id)ans+=dp[i][I];
            res.push_back(ans%mod);
        }
        printf("%lld\n", linear_seq::gao(res, m - 1) % mod);
    }
}T;
char s[N];
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef local
    freopen("../in.txt", "r", stdin);
    clock_t beg=clock();
#endif
    int n,m;cin>>n>>m;
    f(i,1,n){
        cin>>s+1;
        T.insert(s);
    }
    T.build_mat(m);
    debug(clock()-beg);
}

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <map>
#define ls id<<1
#define rs id<<1|1
#define ll long long
const int N=200000+10;
const int mod=998244353;
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
	x=0;int f=0;char c=gc();
	while(!isdigit(c)) f|=c=='-',c=gc();
	while(isdigit(c)) x=x*10+c-'0',c=gc();
	if(f) x=-x;
}
int plus(int x,int y){return x+y>=mod?x+y-mod:x+y;}
#define mul(x,y) (1ll*(x)*(y)%mod)
template <class T>
void ckmin(T &x,T y){x=x<y?x:y;}
template <class T>
void ckmax(T &x,T y){x=x>y?x:y;}
int GCD(int x,int y){return y?GCD(y,x%y):x;}
int n,m;
char s[20];
int root=1,ch[200][52],cnt,tot=1,Id[200][200],endp[200];
struct Matrix
{
	int dx[200][200];
	Matrix(){memset(dx,0,sizeof dx);}
	Matrix friend operator *(Matrix a,Matrix b)
	{
		Matrix ret;
		for(int i=1;i<=cnt;i++)
			for(int j=1;j<=cnt;j++)
				for(int k=1;k<=cnt;k++)
					ret.dx[i][j]=plus(ret.dx[i][j],mul(a.dx[i][k],b.dx[k][j]));
		return ret;
	}
}D;
int q[400],l,r;
bool ck(int u,int v)
{
	q[l=r=1]=u;
	while(l<=r)
	{
		int now=q[l++];
		if(now==v) return true;
		if(root==now) continue;
		for(int i=0;i<52;i++)
			if(ch[now][i])
				q[++r]=ch[now][i];
	}
	return false;
}
void ins()
{
	scanf("%s",s+1);
	l=strlen(s+1);
	int now=root;
	for(int i=1;i<l;i++)
	{
		if(!ch[now][s[i]-'a']) ch[now][s[i]-'a']=++tot;
		now=ch[now][s[i]-'a'];
	}
	ch[now][s[l]-'a'+26]=root;
	//endp[now]=1;
}
Matrix qmp(Matrix x,int y)
{
	Matrix ret=x;--y;
	while(y)
	{
		if(y&1) ret=ret*x;
		x=x*x;
		y>>=1;
	}
	return ret;
}
void work()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) ins();
	for(int i=1;i<=tot;i++)
		for(int j=1;j<=tot;j++)
			if(ck(i,j)||ck(j,i))
				Id[i][j]=++cnt;
	fprintf(stderr,"cnt:%d tot:%d\n",cnt,tot);
	for(int i=1;i<=tot;i++)
		for(int j=1;j<=tot;j++)
			if(ck(i,j)||ck(j,i))
			{
				for(int k=0;k<26;k++)
				{
					if(ch[i][k]&&ch[j][k])
						D.dx[Id[i][j]][Id[ch[i][k]][ch[j][k]]]=1;
					if(ch[i][k+26]&&ch[j][k])
						D.dx[Id[i][j]][Id[ch[i][k+26]][ch[j][k]]]=1;
					if(ch[i][k]&&ch[j][k+26])
						D.dx[Id[i][j]][Id[ch[i][k]][ch[j][k+26]]]=1;
					if(ch[i][k+26]&&ch[j][k+26])
						D.dx[Id[i][j]][Id[ch[i][k+26]][ch[j][k+26]]]=1;
					/*if(ch[i][k]&&endp[j]&&ch[root][k])
						D.dx[Id[i][j]][Id[ch[i][k]][ch[root][k]]]=1;
					if(endp[i]&&ch[root][k]&&ch[j][k])
						D.dx[Id[i][j]][Id[ch[root][k]][ch[j][k]]]=1;
					if(endp[i]&&endp[j]&&ch[root][k])
						D.dx[Id[i][j]][Id[ch[root][k]][ch[root][k]]]=1;*/
				}
			}
	//fprintf(stderr,"%d\n",D.dx[1][1]);
	printf("%d\n",qmp(D,m).dx[1][1]);
}
int main()
{
	//freopen("data.in","r",stdin);
	//freopen("Dew.out","w",stdout);
	int T=1;
	//read(T);
	//scanf("%d",&T);
	while(T--) work();
	return 0;
}

#line 1 "codeforces-workspace/contest/1511/f/f.cpp"
// #undef _GLIBCXX_DEBUG
// #define NDEBUG
#include <bits/extc++.h>

#line 2 "Library/lib/alias"

/**
 * @file alias
 * @brief Alias
 */

#line 13 "Library/lib/alias"

#line 2 "Library/lib/bit"

#if __cplusplus > 201703L

#include <bit>

#else

#ifndef _GLIBCXX_BIT
#define _GLIBCXX_BIT 1

#include <limits>
#include <type_traits>

namespace std {

template <typename _Tp> constexpr _Tp __rotl(_Tp __x, int __s) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  const int __r = __s % _Nd;
  if (__r == 0)
    return __x;
  else if (__r > 0)
    return (__x << __r) | (__x >> ((_Nd - __r) % _Nd));
  else
    return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd));  // rotr(x, -r)
}

template <typename _Tp> constexpr _Tp __rotr(_Tp __x, int __s) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  const int __r = __s % _Nd;
  if (__r == 0)
    return __x;
  else if (__r > 0)
    return (__x >> __r) | (__x << ((_Nd - __r) % _Nd));
  else
    return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd));  // rotl(x, -r)
}

template <typename _Tp> constexpr int __countl_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) {
    constexpr int __diff = _Nd_u - _Nd;
    return __builtin_clz(__x) - __diff;
  } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) {
    constexpr int __diff = _Nd_ul - _Nd;
    return __builtin_clzl(__x) - __diff;
  } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) {
    constexpr int __diff = _Nd_ull - _Nd;
    return __builtin_clzll(__x) - __diff;
  } else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    unsigned long long __high = __x >> _Nd_ull;
    if (__high != 0) {
      constexpr int __diff = (2 * _Nd_ull) - _Nd;
      return __builtin_clzll(__high) - __diff;
    }
    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    return (_Nd - _Nd_ull) + __builtin_clzll(__low);
  }
}

template <typename _Tp> constexpr int __countl_one(_Tp __x) noexcept {
  if (__x == numeric_limits<_Tp>::max()) return numeric_limits<_Tp>::digits;
  return __countl_zero<_Tp>((_Tp)~__x);
}

template <typename _Tp> constexpr int __countr_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
    return __builtin_ctz(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
    return __builtin_ctzl(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
    return __builtin_ctzll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    if (__low != 0) return __builtin_ctzll(__low);
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_ctzll(__high) + _Nd_ull;
  }
}

template <typename _Tp> constexpr int __countr_one(_Tp __x) noexcept {
  if (__x == numeric_limits<_Tp>::max()) return numeric_limits<_Tp>::digits;
  return __countr_zero((_Tp)~__x);
}

template <typename _Tp> constexpr int __popcount(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return 0;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
    return __builtin_popcount(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
    return __builtin_popcountl(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
    return __builtin_popcountll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_popcountll(__low) + __builtin_popcountll(__high);
  }
}

template <typename _Tp> constexpr bool __has_single_bit(_Tp __x) noexcept {
  return __popcount(__x) == 1;
}

template <typename _Tp> constexpr _Tp __bit_ceil(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0 || __x == 1) return 1;
  auto __shift_exponent = _Nd - __countl_zero((_Tp)(__x - 1u));
#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
  if (!__builtin_is_constant_evaluated()) {
    __glibcxx_assert(__shift_exponent != numeric_limits<_Tp>::digits);
  }
#endif
  using __promoted_type = decltype(__x << 1);
  if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) {
    const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2;
    __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp;
  }
  return (_Tp)1u << __shift_exponent;
}

template <typename _Tp> constexpr _Tp __bit_floor(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0) return 0;
  return (_Tp)1u << (_Nd - __countl_zero((_Tp)(__x >> 1)));
}

template <typename _Tp> constexpr _Tp __bit_width(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  return _Nd - __countl_zero(__x);
}

}  // namespace std

#endif

#endif
#line 2 "Library/lib/limits"

#line 4 "Library/lib/limits"

namespace workspace {

template <class _Tp> struct numeric_limits : std::numeric_limits<_Tp> {};

#ifdef __SIZEOF_INT128__

template <> struct numeric_limits<__uint128_t> {
  constexpr static __uint128_t max() { return ~__uint128_t(0); }
  constexpr static __uint128_t min() { return 0; }
};

template <> struct numeric_limits<__int128_t> {
  constexpr static __int128_t max() {
    return numeric_limits<__uint128_t>::max() >> 1;
  }
  constexpr static __int128_t min() { return -max() - 1; }
};

#endif

}  // namespace workspace
#line 16 "Library/lib/alias"

namespace workspace {

constexpr char eol = '\n';

using namespace std;

using i32 = int_least32_t;
using u32 = uint_least32_t;
using i64 = int_least64_t;
using u64 = uint_least64_t;

#ifdef __SIZEOF_INT128__
using i128 = __int128_t;
using u128 = __uint128_t;
#else
#warning 128bit integer is not available.
#endif

namespace _alias_impl {

template <class> struct first_arg { using type = void; };

template <class _Tp, class = void> struct parse_comp : first_arg<_Tp> {};

template <class _Tp>
struct parse_comp<_Tp, std::__void_t<decltype(&_Tp::operator())>>
    : first_arg<decltype(&_Tp::operator())> {};

template <class _R, class _Tp, class... _Args>
struct first_arg<_R(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _R, class _Tp, class... _Args>
struct first_arg<_R (*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...) const> {
  using type = _Tp;
};

}  // namespace _alias_impl

template <class _Tp = void, class _Compare = std::less<_Tp>>
decltype(auto) make_priority_queue(_Compare __x = _Compare()) noexcept {
  using type = std::conditional_t<
      std::is_void<_Tp>::value,
      std::decay_t<typename _alias_impl::parse_comp<_Compare>::type>, _Tp>;

  return std::priority_queue<type, std::vector<type>, _Compare>(__x);
}

template <class _Tp = void, class _Compare = std::less<_Tp>>
decltype(auto) make_set(_Compare __x = _Compare()) noexcept {
  using type = std::conditional_t<
      std::is_void<_Tp>::value,
      std::decay_t<typename _alias_impl::parse_comp<_Compare>::type>, _Tp>;

  return std::set<type, _Compare>(__x);
}

template <class _Key, class _Mapped, class _Compare = std::less<_Key>>
decltype(auto) make_map(_Compare __x = _Compare()) noexcept {
  return std::map<_Key, _Mapped, _Compare>(__x);
}

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T2 &>() <
                              std::declval<const _T1 &>())>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y) noexcept {
  return __y < __x ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T2 &>(), std::declval<const _T1 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__y, __x) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp min(std::initializer_list<_Tp> __x) noexcept {
  return *std::min_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp min(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::min_element(__x.begin(), __x.end(), __comp);
}

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T1 &>() <
                              std::declval<const _T2 &>())>

constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y) noexcept {
  return __x < __y ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T1 &>(), std::declval<const _T2 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__x, __y) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp max(std::initializer_list<_Tp> __x) noexcept {
  return *std::max_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp max(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::max_element(__x.begin(), __x.end(), __comp);
}

template <typename _Tp> constexpr _Tp __bsf(_Tp __x) noexcept {
  return std::__countr_zero(__x);
}

template <typename _Tp> constexpr _Tp __bsr(_Tp __x) noexcept {
  return std::__bit_width(__x) - 1;
}

}  // namespace workspace
#line 6 "codeforces-workspace/contest/1511/f/f.cpp"
// #include "lib/cxx20"
#line 2 "Library/lib/direct"

/*
 * @file direct
 * @brief Pragma Directive
 */

#ifdef ONLINE_JUDGE

#pragma GCC optimize("O3")
#pragma GCC target("avx,avx2")
#pragma GCC optimize("unroll-loops")

#endif
#line 8 "codeforces-workspace/contest/1511/f/f.cpp"
// #include "lib/opt"
#line 2 "Library/src/sys/clock.hpp"

/*
 * @fn clock.hpp
 * @brief Clock
 */

#line 9 "Library/src/sys/clock.hpp"

namespace workspace {

using namespace std::chrono;

namespace internal {
// The start time of the program.
const auto start_time{system_clock::now()};
}  // namespace internal

/*
 * @fn elapsed
 * @return elapsed time of the program
 */
int64_t elapsed() {
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - internal::start_time).count();
}

}  // namespace workspace
#line 2 "Library/src/sys/ejection.hpp"

/**
 * @file ejection.hpp
 * @brief Ejection
 */

#line 9 "Library/src/sys/ejection.hpp"

namespace workspace {

namespace internal {

struct ejection {
  bool exit = 0;
};

}  // namespace internal

/**
 * @brief eject from a try block, throw nullptr
 * @param arg output
 */
template <class Tp> void eject(Tp const &arg) {
  std::cout << arg << "\n";
  throw internal::ejection{};
}

void exit() { throw internal::ejection{true}; }

}  // namespace workspace
#line 2 "Library/src/sys/iteration.hpp"

/**
 * @file iteration.hpp
 * @brief Case Iteration
 */

#line 9 "Library/src/sys/iteration.hpp"

#line 11 "Library/src/sys/iteration.hpp"

namespace workspace {

void main();

struct {
  // 1-indexed
  unsigned current{0};
  unsigned total{1};

  void read() { (std::cin >> total).ignore(); }

  int iterate() {
    static bool once = false;
    assert(!once);
    once = true;
    while (current++ < total) {
      try {
        main();
      } catch (internal::ejection const& status) {
        if (status.exit) break;
      }
    }
    return 0;
  }
} case_info;

}  // namespace workspace
#line 10 "codeforces-workspace/contest/1511/f/f.cpp"
// #include "lib/utils"

#line 2 "Library/src/utils/io/setup.hpp"

/**
 * @file setup.hpp
 * @brief I/O Setup
 */

#line 10 "Library/src/utils/io/setup.hpp"

namespace workspace {

/**
 * @brief Setup I/O.
 * @param __n Standard output precision
 */
void io_setup(int __n) {
  std::cin.tie(0)->sync_with_stdio(0);
  std::cout << std::fixed << std::setprecision(__n);

#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (std::cin >> bufc)
      std::cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}

}  // namespace workspace
#line 2 "Library/src/utils/py-like/range.hpp"

/**
 * @file range.hpp
 * @brief Range
 */

#line 9 "Library/src/utils/py-like/range.hpp"

#line 2 "Library/src/utils/iterator/reverse.hpp"

/*
 * @file reverse_iterator.hpp
 * @brief Reverse Iterator
 */

#if __cplusplus >= 201703L

#include <iterator>
#include <optional>

namespace workspace {

/*
 * @class reverse_iterator
 * @brief Wrapper class for `std::reverse_iterator`.
 * @see http://gcc.gnu.org/PR51823
 */
template <class Iterator>
class reverse_iterator : public std::reverse_iterator<Iterator> {
  using base_std = std::reverse_iterator<Iterator>;
  std::optional<typename base_std::value_type> deref;

 public:
  using base_std::reverse_iterator;

  constexpr typename base_std::reference operator*() noexcept {
    if (!deref) {
      Iterator tmp = base_std::current;
      deref = *--tmp;
    }
    return deref.value();
  }

  constexpr reverse_iterator &operator++() noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator &operator--() noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator operator++(int) noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator operator--(int) noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
};

}  // namespace workspace

#endif
#line 2 "Library/src/utils/py-like/reversed.hpp"

/**
 * @file reversed.hpp
 * @brief Reversed
 */

#include <initializer_list>
#line 10 "Library/src/utils/py-like/reversed.hpp"

namespace workspace {

namespace _reversed_impl {

template <class _Container> class reversed {
  _Container __cont;

 public:
  constexpr reversed(_Container &&__cont) noexcept : __cont(__cont) {}

  constexpr decltype(auto) begin() noexcept { return std::rbegin(__cont); }
  constexpr decltype(auto) begin() const noexcept {
    return std::rbegin(__cont);
  }

  constexpr decltype(auto) end() noexcept { return std::rend(__cont); }
  constexpr decltype(auto) end() const noexcept { return std::rend(__cont); }

  constexpr decltype(auto) size() const noexcept { return std::size(__cont); }
};

}  // namespace _reversed_impl

template <class _Container>
constexpr decltype(auto) reversed(_Container &&__cont) noexcept {
  return _reversed_impl::reversed<_Container>{std::forward<_Container>(__cont)};
}

template <class _Tp>
constexpr decltype(auto) reversed(
    std::initializer_list<_Tp> &&__cont) noexcept {
  return _reversed_impl::reversed<std::initializer_list<_Tp>>{
      std::forward<std::initializer_list<_Tp>>(__cont)};
}

}  // namespace workspace
#line 12 "Library/src/utils/py-like/range.hpp"

#if __cplusplus >= 201703L

namespace workspace {

template <class _Index> class range {
  _Index __first, __last;

 public:
  class iterator {
    _Index current;

   public:
    using difference_type = std::ptrdiff_t;
    using value_type = _Index;
    using reference = typename std::add_const<_Index>::type &;
    using pointer = iterator;
    using iterator_category = std::bidirectional_iterator_tag;

    constexpr iterator(const _Index &__i = _Index()) noexcept : current(__i) {}

    constexpr bool operator==(const iterator &__x) const noexcept {
      return current == __x.current;
    }
    constexpr bool operator!=(const iterator &__x) const noexcept {
      return current != __x.current;
    }

    constexpr iterator &operator++() noexcept {
      ++current;
      return *this;
    }
    constexpr iterator &operator--() noexcept {
      --current;
      return *this;
    }

    constexpr reference operator*() const noexcept { return current; }
  };

  constexpr range(_Index __first, _Index __last) noexcept
      : __first(__first), __last(__last) {}
  constexpr range(_Index __last) noexcept : __first(), __last(__last) {}

  constexpr iterator begin() const noexcept { return iterator{__first}; }
  constexpr iterator end() const noexcept { return iterator{__last}; }

  constexpr reverse_iterator<iterator> rbegin() const noexcept {
    return reverse_iterator<iterator>(end());
  }
  constexpr reverse_iterator<iterator> rend() const noexcept {
    return reverse_iterator<iterator>(begin());
  }

  constexpr size_t size() const noexcept {
    return std::distance(__first, __last);
  }
};

template <class... _Args>
constexpr decltype(auto) rrange(_Args &&...__args) noexcept {
  return reversed(range(std::forward<_Args>(__args)...));
}

}  // namespace workspace

#endif
#line 14 "codeforces-workspace/contest/1511/f/f.cpp"

signed main() {
  using namespace workspace;

  io_setup(15);

  /* given
    case_info.read();  //*/

  /* unspecified
    case_info.total = -1;  //*/

  return case_info.iterate();
}

#line 2 "Library/src/algebra/linear/matrix.hpp"

/**
 * @file matrix.hpp
 * @brief Matrix
 * @date 2021-02-15
 *
 *
 */

#line 13 "Library/src/algebra/linear/matrix.hpp"

namespace workspace {

/**
 * @brief Fixed size matrix.
 *
 * @tparam _Scalar
 * @tparam _Rows Number of rows
 * @tparam _Cols Number of columns
 */
template <class _Scalar, std::size_t _Rows = 0, std::size_t _Cols = _Rows>
class matrix {
 public:
  _Scalar __data[_Rows][_Cols] = {};

  using value_type = _Scalar;
  using size_type = std::size_t;

  constexpr static matrix eye() {
    static_assert(_Rows == _Cols);

    matrix __e;
    for (size_type __d = 0; __d != _Rows; ++__d) __e.__data[__d][__d] = 1;
    return __e;
  }

  constexpr operator decltype((__data))() { return __data; }
  constexpr operator decltype(std::declval<const matrix>().__data)
      const&() const {
    return __data;
  }

  constexpr auto begin() { return __data; }
  constexpr auto begin() const { return __data; }

  constexpr auto end() { return __data + _Rows; }
  constexpr auto end() const { return __data + _Rows; }

  constexpr size_type rows() const { return _Rows; }

  constexpr size_type cols() const { return _Cols; }

  constexpr auto transpose() const {
    matrix<_Scalar, _Cols, _Rows> __t;

    for (size_type __r = 0; __r != _Rows; ++__r)
      for (size_type __c = 0; __c != _Cols; ++__c)
        __t.__data[__c][__r] = __data[__r][__c];

    return __t;
  }

  constexpr matrix operator+() const { return *this; }

  constexpr matrix operator-() const {
    matrix __cp = *this;

    for (auto& __v : __cp.__data)
      for (auto& __e : __v) __e = -__e;

    return __cp;
  }

  template <class _Matrix> constexpr matrix& operator+=(const _Matrix& __x) {
    auto __m = std::min(_Rows, __x.rows());
    auto __n = std::min(_Cols, __x.cols());

    for (size_type __r = 0; __r != __m; ++__r)
      for (size_type __c = 0; __c != __n; ++__c)
        __data[__r][__c] += __x[__r][__c];

    return *this;
  }

  template <class _Matrix>
  constexpr matrix operator+(const _Matrix& __x) const {
    return matrix(*this) += __x;
  }

  template <class _Matrix> constexpr matrix& operator-=(const _Matrix& __x) {
    auto __m = std::min(_Rows, __x.rows());
    auto __n = std::min(_Cols, __x.cols());

    for (size_type __r = 0; __r != __m; ++__r)
      for (size_type __c = 0; __c != __n; ++__c)
        __data[__r][__c] -= __x[__r][__c];

    return *this;
  }

  template <class _Matrix>
  constexpr matrix operator-(const _Matrix& __x) const {
    return matrix(*this) -= __x;
  }

  template <class _Scalar2>
  constexpr matrix& operator*=(const matrix<_Scalar2, _Cols, _Cols>& __x) {
    if (this == &__x) return operator=(operator*(__x));

    for (auto& __r : __data) {
      _Scalar __tmp[_Cols] = {};

      auto __v = *__x.__data;
      for (auto& __w : __tmp) {
        auto __i = __v++;
        for (const auto& __e : __r) __w += __e * *__i, __i += _Cols;
      }

      auto __w = __tmp;
      for (auto& __e : __r) __e = std::move(*__w++);
    }

    return *this;
  }

  template <class _Scalar2, size_type _Rows2, size_type _Cols2>
  constexpr auto operator*(const matrix<_Scalar2, _Rows2, _Cols2>& __x) const {
    matrix<typename std::common_type<_Scalar, _Scalar2>::type, _Rows, _Cols2>
        __m;

    auto __w = *__m.__data;
    for (const auto& __r : __data)
      for (auto __v = *__x.__data, __v_end = __v + _Cols2; __v != __v_end;
           ++__w) {
        auto __i = __v++;
        for (auto __e = __r; __e != __r + std::min(_Cols, _Rows2); ++__e)
          *__w += *__e * *__i, __i += _Cols2;
      }

    return __m;
  }

  template <class _Matrix>
  constexpr
      typename std::enable_if<!std::is_convertible<_Matrix, value_type>::value,
                              matrix<_Scalar>>::type
      operator*(const _Matrix& __x) const {
    matrix<_Scalar> __m(_Rows, __x.cols());

    for (size_type __r = 0; __r != _Rows; ++__r)
      for (size_type __i = 0; __i != __x.cols(); ++__i)
        for (size_type __c = 0; __c != std::min(_Cols, __x.rows()); ++__c)
          __m[__r][__i] += __data[__r][__c] * __x[__c][__i];

    return __m;
  }

  constexpr matrix& operator*=(const value_type& __x) {
    for (auto& __v : __data)
      for (auto& __e : __v) __e *= __x;

    return *this;
  }

  constexpr matrix operator*(const value_type& __x) const {
    return matrix(*this) *= __x;
  }

  constexpr matrix& operator/=(const value_type& __x) {
    assert(__x != value_type(0));

    for (auto& __v : __data)
      for (auto& __e : __v) __e /= __x;

    return *this;
  }

  constexpr matrix operator/(const value_type& __x) const {
    return matrix(*this) /= __x;
  }

  template <class _Int> constexpr matrix pow(_Int __e) const {
    assert(0 <= __e);

    matrix __m = eye();
    for (matrix __cp = *this; __e; __cp *= __cp, __e >>= 1)
      if (__e & 1) __m *= __cp;

    return __m;
  }

  template <class _Os>
  constexpr friend _Os& operator<<(_Os& __os, const matrix& __x) {
    for (auto __i = __x.begin(); __i != __x.end(); ++__i, __os << '\n')
      for (size_type __c = 0; __c != _Cols; ++__c)
        __c ? void(__os << ' ') : (void)0, __os << *(*__i + __c);

    return __os;
  }
};  // namespace workspace

/**
 * @brief Dynamic matrix.
 *
 * @tparam _Scalar
 * @tparam _Rows Number of rows
 * @tparam _Cols Number of columns
 */
template <class _Scalar>
class matrix<_Scalar, 0, 0> : public std::valarray<std::valarray<_Scalar>> {
  using base = std::valarray<std::valarray<_Scalar>>;
  using row_type = typename base::value_type;

 public:
  using value_type = _Scalar;
  using size_type = std::size_t;

  using base::operator[];

  static matrix eye(size_type __n) {
    matrix __e(__n, __n);
    for (size_type __d = 0; __d != __n; ++__d) __e[__d][__d] = 1;
    return __e;
  }

  matrix() = default;

  matrix(size_type __n) : matrix(__n, __n) {}

  matrix(size_type __m, size_type __n) : base(row_type(__n), __m) {}

  template <class _Tp, typename = typename std::enable_if<
                           std::is_constructible<base, _Tp>::value &&
                           !std::is_constructible<size_type, _Tp>::value>::type>
  matrix(_Tp&& __x) : base(__x) {}

  matrix(std::initializer_list<row_type> __x) : base(__x) {}

  size_type rows() const { return base::size(); }

  size_type cols() const { return rows() ? operator[](0).size() : 0; }

  matrix transpose() const {
    matrix __t(cols(), rows());

    for (size_type __r = 0; __r != rows(); ++__r)
      for (size_type __c = 0; __c != cols(); ++__c)
        __t[__c][__r] = operator[](__r)[__c];

    return __t;
  }

  void resize(size_type __m, size_type __n) {
    matrix __t(__m, __n);

    if (rows() < __m) __m = rows();
    if (cols() < __n) __n = cols();

    for (size_type __r = 0; __r != __m; ++__r)
      for (size_type __c = 0; __c != __n; ++__c)
        __t[__r][__c] = std::move(operator[](__r)[__c]);

    base::swap(__t);
  }

  // binary operators {{

  template <class _Matrix, typename = void>
  struct is_valarray_based : std::false_type {};

  template <class _Matrix>
  struct is_valarray_based<
      _Matrix,
      typename std::enable_if<std::is_same<
          row_type, typename std::decay<decltype(
                        std::declval<_Matrix>()[0])>::type>::value>::type>
      : std::true_type {};

  template <class _Matrix>
  typename std::enable_if<!std::is_convertible<_Matrix, value_type>::value,
                          matrix&>::type
  operator*=(_Matrix&& __x) {
    return *this = operator*(std::forward<_Matrix>(__x));
  }

  template <class _Matrix>
  typename std::enable_if<!std::is_convertible<_Matrix, value_type>::value,
                          matrix>::type
  operator*(const _Matrix& __x) const {
    matrix __m(rows(), __x.cols());

    if constexpr (is_valarray_based<_Matrix>::value)
      for (size_type __r = 0; __r != rows(); ++__r)
        for (size_type __c = 0; __c != std::min(cols(), __x.rows()); ++__c)
          __m[__r] += operator[](__r)[__c] * __x[__c];

    else
      for (size_type __r = 0; __r != rows(); ++__r)
        for (size_type __i = 0; __i != __x.cols(); ++__i)
          for (size_type __c = 0; __c != std::min(cols(), __x.rows()); ++__c)
            __m[__r][__i] += operator[](__r)[__c] * __x[__c][__i];

    return __m;
  }

  matrix& operator*=(const value_type& __x) {
    for (size_type __r = 0; __r != rows(); ++__r)
      operator[](__r).operator*=(__x);

    return *this;
  }

  matrix operator*(const value_type& __x) const { return matrix(*this) *= __x; }

  friend matrix operator*(const value_type& __x, matrix __i) {
    for (size_type __r = 0; __r != __i.rows(); ++__r)
      __i.operator[](__r) = __x * __i.operator[](__r);

    return __i;
  }

  matrix& operator/=(const value_type& __x) {
    assert(__x != value_type(0));

    for (size_type __r = 0; __r != rows(); ++__r)
      operator[](__r).operator/=(__x);

    return *this;
  }

  matrix operator/(const value_type& __x) const { return matrix(*this) /= __x; }

  // }} binary operators

  template <class _Int> matrix pow(_Int __e) const {
    assert(0 <= __e);

    matrix __m = eye(rows());
    for (matrix __cp = *this; __e; __cp *= __cp, __e >>= 1)
      if (__e & 1) __m *= __cp;

    return __m;
  }

  // template <class _Is> friend _Is& operator>>(_Is& __is, matrix& __x) {
  //   for (size_type __r = 0; __r != __x.rows(); ++__r)
  //     for (size_type __c = 0; __c != __x.cols(); ++__c)
  //       __is >> __x.operator[](__r).operator[](__c);

  //   return __is;
  // }

  template <class _Os> friend _Os& operator<<(_Os& __os, const matrix& __x) {
    for (size_type __r = 0; __r != __x.rows(); ++__r, __os << '\n')
      for (size_type __c = 0; __c != __x.cols(); ++__c)
        __c ? void(__os << ' ') : (void)0,
            __os << __x.operator[](__r).operator[](__c);

    return __os;
  }
};

}  // namespace workspace
#line 2 "Library/src/modular/modint.hpp"

/**
 * @file modint.hpp
 *
 * @brief Modular Arithmetic
 */

#line 12 "Library/src/modular/modint.hpp"

#line 2 "Library/src/number_theory/sqrt_mod.hpp"

/**
 * @file sqrt_mod.hpp
 * @brief Tonelli-Shanks Algorithm
 */

#line 2 "Library/src/number_theory/pow_mod.hpp"

/**
 * @file mod_pow.hpp
 * @brief Modular Exponentiation
 */

#line 9 "Library/src/number_theory/pow_mod.hpp"

#line 2 "Library/src/utils/sfinae.hpp"

/**
 * @file sfinae.hpp
 * @brief SFINAE
 */

#line 10 "Library/src/utils/sfinae.hpp"
#include <type_traits>

#ifndef __INT128_DEFINED__

#ifdef __SIZEOF_INT128__
#define __INT128_DEFINED__ 1
#else
#define __INT128_DEFINED__ 0
#endif

#endif

namespace std {

#if __INT128_DEFINED__

template <> struct make_signed<__uint128_t> { using type = __int128_t; };
template <> struct make_signed<__int128_t> { using type = __int128_t; };

template <> struct make_unsigned<__uint128_t> { using type = __uint128_t; };
template <> struct make_unsigned<__int128_t> { using type = __uint128_t; };

template <> struct is_signed<__uint128_t> : std::false_type {};
template <> struct is_signed<__int128_t> : std::true_type {};

template <> struct is_unsigned<__uint128_t> : std::true_type {};
template <> struct is_unsigned<__int128_t> : std::false_type {};

#endif

}  // namespace std

namespace workspace {

template <class Tp, class... Args> struct variadic_front { using type = Tp; };

template <class... Args> struct variadic_back;

template <class Tp> struct variadic_back<Tp> { using type = Tp; };

template <class Tp, class... Args> struct variadic_back<Tp, Args...> {
  using type = typename variadic_back<Args...>::type;
};

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

/**
 * @brief Return type of subscripting ( @c [] ) access.
 */
template <class _Tp>
using subscripted_type =
    typename std::decay<decltype(std::declval<_Tp&>()[0])>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class _Tp, class = std::nullptr_t>
struct has_begin : std::false_type {};

template <class _Tp>
struct has_begin<_Tp, decltype(std::begin(std::declval<_Tp>()), nullptr)>
    : std::true_type {};

template <class _Tp, class = std::nullptr_t>
struct has_mod : std::false_type {};

template <class _Tp>
struct has_mod<_Tp, decltype(_Tp::mod, nullptr)> : std::true_type {};

template <class _Tp, class = void> struct is_integral_ext : std::false_type {};
template <class _Tp>
struct is_integral_ext<
    _Tp, typename std::enable_if<std::is_integral<_Tp>::value>::type>
    : std::true_type {};

#if __INT128_DEFINED__

template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};

#endif

#if __cplusplus >= 201402

template <class _Tp>
constexpr static bool is_integral_ext_v = is_integral_ext<_Tp>::value;

#endif

template <typename _Tp, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename _Tp>
struct multiplicable_uint<
    _Tp,
    typename std::enable_if<(2 < sizeof(_Tp)) &&
                            (!__INT128_DEFINED__ || sizeof(_Tp) <= 4)>::type> {
  using type = uint_least64_t;
};

#if __INT128_DEFINED__

template <typename _Tp>
struct multiplicable_uint<_Tp,
                          typename std::enable_if<(4 < sizeof(_Tp))>::type> {
  using type = __uint128_t;
};

#endif

template <typename _Tp> struct multiplicable_int {
  using type =
      typename std::make_signed<typename multiplicable_uint<_Tp>::type>::type;
};

template <typename _Tp> struct multiplicable {
  using type = std::conditional_t<
      is_integral_ext<_Tp>::value,
      std::conditional_t<std::is_signed<_Tp>::value,
                         typename multiplicable_int<_Tp>::type,
                         typename multiplicable_uint<_Tp>::type>,
      _Tp>;
};

}  // namespace workspace
#line 11 "Library/src/number_theory/pow_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular exponentiation.
 *
 * @param __x
 * @param __n Exponent
 * @param __mod Modulus
 * @return
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> pow_mod(
    _Tp __x, _Tp __n, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  mul_type __y{1};

  while (__n) {
    if (__n & 1) (__y *= __x) %= __mod;
    __x = (mul_type)__x * __x % __mod;
    __n >>= 1;
  }

  return __y;
};

}  // namespace workspace
#line 10 "Library/src/number_theory/sqrt_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular square root.
 *
 * @param __x
 * @param __mod Modulus
 * @return One if it exists. Otherwise -1.
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> sqrt_mod(
    _Tp __x, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  if (!__x) return 0;

  if (__mod == 2) return __x;

  if (pow_mod(__x, __mod >> 1, __mod) != 1) return -1;

  _Tp __z = __builtin_ctz(__mod - 1), __q = __mod >> __z;

  mul_type __a = pow_mod(__x, (__q + 1) >> 1, __mod), __b = 2;
  while (pow_mod<_Tp>(__b, __mod >> 1, __mod) == 1) ++__b;
  __b = pow_mod<_Tp>(__b, __q, __mod);

  _Tp __shift = 0;

  for (auto __r = __a * __a % __mod * pow_mod(__x, __mod - 2, __mod) % __mod;
       __r != 1; (__r *= (__b *= __b) %= __mod) %= __mod) {
    auto __bsf = __z;

    for (auto __e = __r; __e != 1; --__bsf) (__e *= __e) %= __mod;

    while (++__shift != __bsf) (__b *= __b) %= __mod;

    (__a *= __b) %= __mod;
  }

  return __a;
};

}  // namespace workspace
#line 15 "Library/src/modular/modint.hpp"

namespace workspace {

namespace _modint_impl {

/**
 * @brief Modular arithmetic.
 *
 * @tparam Mod identifier, which represents modulus if positive
 * @tparam Storage Reserved size for inverse calculation
 */
template <auto Mod, unsigned Storage> struct modint {
  static_assert(is_integral_ext<decltype(Mod)>::value,
                "Mod must be integral type.");

  using mod_type = typename std::make_signed<typename std::conditional<
      0 < Mod, typename std::add_const<decltype(Mod)>::type,
      decltype(Mod)>::type>::type;

  using value_type = typename std::decay<mod_type>::type;

  using mul_type = typename multiplicable_uint<value_type>::type;

  // Modulus
  static mod_type mod;

  static unsigned storage;

  constexpr static void reserve(unsigned __n) noexcept { storage = __n; }

 private:
  value_type value = 0;

  struct direct_ctor_t {};
  constexpr static direct_ctor_t direct_ctor_tag{};

  // Direct constructor
  template <class _Tp> constexpr modint(_Tp __n, direct_ctor_t) : value(__n) {}

 public:
  constexpr modint() noexcept = default;

  template <class _Tp, typename std::enable_if<
                           is_integral_ext<_Tp>::value>::type * = nullptr>
  constexpr modint(_Tp __n) noexcept
      : value((__n %= mod) < 0 ? __n += mod : __n) {}

  constexpr modint(bool __n) noexcept : value(__n) {}

  constexpr operator value_type() const noexcept { return value; }

  constexpr static modint one() noexcept { return 1; }

  // unary operators {{
  constexpr modint operator++(int) noexcept {
    modint __t{*this};
    operator++();
    return __t;
  }

  constexpr modint operator--(int) noexcept {
    modint __t{*this};
    operator--();
    return __t;
  }

  constexpr modint &operator++() noexcept {
    if (++value == mod) value = 0;
    return *this;
  }

  constexpr modint &operator--() noexcept {
    if (!value)
      value = mod - 1;
    else
      --value;
    return *this;
  }

  constexpr modint operator+() const noexcept { return *this; }

  constexpr modint operator-() const noexcept {
    return {value ? mod - value : 0, direct_ctor_tag};
  }

  // }} unary operators

  // operator+= {{

  constexpr modint &operator+=(const modint &__x) noexcept {
    if ((value += __x.value) >= mod) value -= mod;
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator+=(_Tp const &__x) noexcept {
    if (((value += __x) %= mod) < 0) value += mod;
    return *this;
  }

  // }} operator+=

  // operator+ {{

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator+(_Tp const &__x) const noexcept {
    return modint{*this} += __x;
  }

  constexpr modint operator+(modint __x) const noexcept { return __x += *this; }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator+(_Tp const &__x, modint __y) noexcept {
    return __y += __x;
  }

  // }} operator+

  // operator-= {{

  constexpr modint &operator-=(const modint &__x) noexcept {
    if ((value -= __x.value) < 0) value += mod;
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator-=(_Tp __x) noexcept {
    if (((value -= __x) %= mod) < 0) value += mod;
    return *this;
  }

  // }} operator-=

  // operator- {{

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator-(_Tp const &__x) const noexcept {
    return modint{*this} -= __x;
  }

  constexpr modint operator-(const modint &__x) const noexcept {
    return modint{*this} -= __x;
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator-(_Tp __x, const modint &__y) noexcept {
    if (((__x -= __y.value) %= mod) < 0) __x += mod;
    return {__x, direct_ctor_tag};
  }

  // }} operator-

  // operator*= {{

  constexpr modint &operator*=(const modint &__x) noexcept {
    value =
        static_cast<value_type>(value * static_cast<mul_type>(__x.value) % mod);
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator*=(_Tp __x) noexcept {
    value = static_cast<value_type>(
        value * mul_type((__x %= mod) < 0 ? __x + mod : __x) % mod);
    return *this;
  }

  // }} operator*=

  // operator* {{

  constexpr modint operator*(const modint &__x) const noexcept {
    return {static_cast<mul_type>(value) * __x.value % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator*(_Tp __x) const noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(value) * __x % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator*(_Tp __x, const modint &__y) noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(__x) * __y.value % mod, direct_ctor_tag};
  }

  // }} operator*

 protected:
  static value_type _mem(value_type __x) {
    static std::vector<value_type> __m{0, 1};
    static value_type __i = (__m.reserve(Storage), 1);
    while (__i < __x) {
      ++__i;
      __m.emplace_back(mod - mul_type(mod / __i) * __m[mod % __i] % mod);
    }
    return __m[__x];
  }

  template <class _Tp>
  constexpr static
      typename std::enable_if<is_integral_ext<_Tp>::value, value_type>::type
      _div(mul_type __r, _Tp __x) noexcept {
    assert(__x != _Tp(0));
    if (!__r) return 0;

    std::make_signed_t<_Tp> __v{};
    bool __neg = __x < 0 ? __x = -__x, true : false;

    if (static_cast<decltype(storage)>(__x) < storage)
      __v = _mem(__x);
    else {
      decltype(__v) __y{mod}, __u{1}, __t;

      while (__x)
        __t = __y / __x, __y ^= __x ^= (__y -= __t * __x) ^= __x,
        __v ^= __u ^= (__v -= __t * __u) ^= __u;

      if (__y < 0) __neg ^= 1;
    }

    if (__neg)
      __v = 0 < __v ? mod - __v : -__v;
    else if (__v < 0)
      __v += mod;

    return __r == mul_type(1) ? static_cast<value_type>(__v)
                              : static_cast<value_type>(__r * __v % mod);
  }

 public:
  // operator/= {{

  constexpr modint &operator/=(const modint &__x) noexcept {
    if (value) value = _div(value, __x.value);
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator/=(_Tp __x) noexcept {
    if (value) value = _div(value, __x %= mod);
    return *this;
  }

  // }} operator/=

  // operator/ {{

  constexpr modint operator/(const modint &__x) const noexcept {
    if (!value) return {};
    return {_div(value, __x.value), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator/(_Tp __x) const noexcept {
    if (!value) return {};
    return {_div(value, __x %= mod), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator/(_Tp __x, const modint &__y) noexcept {
    if (!__x) return {};
    if ((__x %= mod) < 0) __x += mod;
    return {_div(__x, __y.value), direct_ctor_tag};
  }

  // }} operator/

  constexpr modint inv() const noexcept { return _div(1, value); }

  template <class _Tp>
  constexpr std::__enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      _Tp __e) const noexcept {
    modint __r{1, direct_ctor_tag};

    for (modint __b{__e < 0 ? __e = -__e, _div(1, value) : value,
                              direct_ctor_tag};
         __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  template <class _Tp>
  friend constexpr std::__enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      modint __b, _Tp __e) noexcept {
    if (__e < 0) {
      __e = -__e;
      __b.value = _div(1, __b.value);
    }

    modint __r{1, direct_ctor_tag};

    for (; __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  constexpr modint sqrt() const noexcept {
    return {sqrt_mod(value, mod), direct_ctor_tag};
  }

  friend constexpr modint sqrt(const modint &__x) noexcept {
    return {sqrt_mod(__x.value, mod), direct_ctor_tag};
  }

  template <class _Os>
  friend _Os &operator<<(_Os &__os, const modint &__x) noexcept {
    return __os << __x.value;
  }

  friend std::istream &operator>>(std::istream &__is, modint &__x) noexcept {
    std::string __s;
    __is >> __s;
    bool __neg = false;
    if (__s.front() == '-') {
      __neg = true;
      __s.erase(__s.begin());
    }
    __x = 0;
    for (char __c : __s) __x = __x * 10 + (__c - '0');
    if (__neg) __x = -__x;
    return __is;
  }
};

template <auto Mod, unsigned Storage>
typename modint<Mod, Storage>::mod_type modint<Mod, Storage>::mod =
    Mod > 0 ? Mod : 0;

template <auto Mod, unsigned Storage>
unsigned modint<Mod, Storage>::storage = Storage;

}  // namespace _modint_impl

/**
 * @brief Modular arithmetic.
 *
 * @tparam Mod modulus
 * @tparam Storage Reserved size for inverse calculation
 */
template <auto Mod, unsigned Storage = 0,
          typename std::enable_if<(Mod > 0)>::type * = nullptr>
using modint = _modint_impl::modint<Mod, Storage>;

/**
 * @brief Runtime modular arithmetic.
 *
 * @tparam type_id uniquely assigned
 * @tparam Storage Reserved size for inverse calculation
 */
template <unsigned type_id = 0, unsigned Storage = 0>
using modint_runtime = _modint_impl::modint<-(signed)type_id, Storage>;

// #define modint_newtype modint_runtime<__COUNTER__>

}  // namespace workspace
#line 31 "codeforces-workspace/contest/1511/f/f.cpp"

namespace workspace {

using mint = modint<998244353>;
using mat = matrix<mint>;

void main() {
  // start here!

  int n, k;
  cin >> n >> k;

  vector<string> wds(n), sufs{""};
  for (auto &&x : wds) {
    cin >> x;
  }

  for (auto t : range(4)) {
    auto cp = sufs;
    for (auto &&s : cp) {
      if (s.size() >= 5) {
        continue;
      }
      for (auto w : wds) {
        reverse(begin(w), end(w));
        sufs.emplace_back(s + w);
      }
    }
  }

  for (auto &&x : sufs) {
    x = x.substr(0, 4);
    reverse(begin(x), end(x));
  }

  sort(begin(sufs), end(sufs));
  sufs.erase(unique(begin(sufs), end(sufs)), end(sufs));

  const auto m = sufs.size();
  mat a(m * 5);

  for (auto i : range(4)) {
    for (auto j : range(m)) {
      a[i * m + j][(i + 1) * m + j] = 1;
    }
  }

  for (auto j : range(m)) {
    for (auto w : wds) {
      auto len = w.size();
      w = sufs[j] + w;
      vector<mint> dp(w.size() + 1);
      dp[0] = 1;
      for (auto i : range(w.size())) {
        for (auto &&x : wds) {
          if (!i && x.size() <= sufs[j].size()) {
            continue;
          }
          if (w.substr(i, x.size()) == x) dp[i + x.size()] += dp[i];
        }
      }
      for (auto i : range(w.size() + 1)) {
        auto enc =
            lower_bound(begin(sufs), end(sufs), w.substr(i)) - begin(sufs);
        if (enc != sufs.size()) a[(len - 1) * m + j][enc] += dp[i];
      }
    }
  }

  a = a.pow(k);
  cout << a[0][0] << "\n";
}

}  // namespace workspace

#include <iostream>
#include <vector>
#include <chrono>
#include <random>
#include <cassert>
#include <map>

std::mt19937 rng((int) std::chrono::steady_clock::now().time_since_epoch().count());

const int ms = 300;
//const int ms = 5 * 8 * 5 * 8 + 4;
const int MOD = 998244353;

template <class T>
T fexp(T x, long long e) {
	T ans(1);
	for(; e > 0; e /= 2) {
		if(e & 1) ans = ans * x;
		x = x * x;
	}
	return ans;
}

template <int mod = MOD>
struct modBase {
	modBase(int v = 0) : val(v < 0 ? v + mod : v) {}
	int val;

	void operator += (modBase<mod> o) { *this = *this + o; }
	void operator -= (modBase<mod> o) { *this = *this - o; }
	void operator *= (modBase<mod> o) { *this = *this * o; }
	//void operator /= (modBase<mod> o) { *this = *this / o; }
	modBase<mod> operator * (modBase<mod> o) { return (int)((long long) val * o.val % mod); }
	//modBase<mod> operator / (modBase<mod> o) { return *this * fexp(o, mod - 2); }
	modBase<mod> operator + (modBase<mod> o) { return val + o.val >= mod ? val + o.val - mod : val + o.val; }
	modBase<mod> operator - (modBase<mod> o) { return val - o.val < 0 ? val - o.val + mod : val - o.val; }

	friend std::ostream& operator << (std::ostream &os, const modBase<mod> &p) {
		return os << p.val;
	}
	friend std::istream& operator >> (std::istream &is, modBase<mod> &p) {
		return is >> p.val;
	}
};

template<const int n, const int m, class T = modBase<>>
struct Matrix {
	T v[n][m];

	Matrix(int d = 0) {
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < m; j++) {
				v[i][j] = T(0);
			}
			if(i < m) {
				v[i][i] = T(d);
			}
		}
	}

	template<int mm>
	Matrix<n, mm, T> operator *(const Matrix<m, mm, T> &o) {
		Matrix<n, mm, T> ans;
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < mm; j++) {
				for(int k = 0; k < m; k++) {
					ans.v[i][j] = ans.v[i][j] + v[i][k] * o.v[k][j];
				}
			}
		}
		return ans;
	}
};

int c = 1;
int trie[ms][26];
int terminal[ms];

void add(const std::string &str) {
	int on = 0;
	for(auto ch : str) {
		//assert(c * c < ms);
		if(trie[on][ch - 'a'] == 0) trie[on][ch - 'a'] = c++;
		on = trie[on][ch - 'a'];
		//std::cout << on << '\n';
	}
	terminal[on]++;
}

int main() {
	//std::cout << "GOT HERE!" << std::endl;
	std::ios_base::sync_with_stdio(false); std::cin.tie(NULL);
	//std::cout << ms << '\n';
	int n, m;
	std::cin >> n >> m;
	while(n--) {
		std::string str;
		std::cin >> str;
		add(str);
	}
	std::map<int, int> mp;
	mp[0] = 0;
	std::vector<int> q(1, 0);
	auto getId = [&](int id) {
		int i = id / c, j = id % c;
		if(i > j) std::swap(i, j);
		id = i * c + j;
		if(!mp.count(id)) {
			int sz = (int) mp.size();
			mp[id] = sz;
			assert(sz < ms);
			q.push_back(id);
		}
		return mp[id];
	};
	Matrix<ms, ms> mat(0);
	for(int wtf = 0; wtf < (int) q.size(); wtf++) {
		int i = q[wtf] / c, j = q[wtf] % c;
		for(int ch = 0; ch < 26; ch++) if(trie[i][ch] && trie[j][ch]) {
			int u = trie[i][ch], v = trie[j][ch];
			mat.v[getId(u * c + v)][getId(i * c + j)] += 1;
			mat.v[getId(0)][getId(i * c + j)] += terminal[u] * terminal[v];
			if(terminal[v]) mat.v[getId(u * c)][getId(i * c + j)] += terminal[v];
			if(terminal[u]) mat.v[getId(v)][getId(i * c + j)];
		}
	}
	std::cout << fexp(mat, m).v[0][0] << '\n';
}

// Sometimes, the questions are complicated - and the answers are simple. //
#pragma GCC optimize ("O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
#pragma GCC optimize ("unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define ld  long double
#define IO ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int mod = 998244353;
const int N = 180;
int res[N][N];
void mul(int a[][N],int b[][N]) {
    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++) {
            res[i][j] = 0;
            for(int k = 0; k < N; k++) {
                res[i][j] = (1LL * a[i][k] * b[k][j] + res[i][j]) % mod;
            }
        }
    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++)
            a[i][j] = res[i][j];
}
void power(int temp[][N], int p) {

    int res[N][N] = {0};
    for(int i = 0; i < N; i++)
        res[i][i] = 1;

    while(p) {
        if(p & 1)
            mul(res, temp);
        mul(temp, temp);
        p >>= 1;
    }

    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++)
            temp[i][j] = res[i][j];
}
int n, m ;
int trie[50][30], node_ind;
bool final_state[50];
void insert(string & s) {
    int node = 0;
    for(auto i : s) {
        int cur = i - 'a';
        if(!trie[node][cur])
            trie[node][cur] = ++node_ind;
        node = trie[node][cur];
    }
    final_state[node] = true;
}
map<pair<int, int>, int >mop;
set<pair<int, int> > vis;
int get_ind(int x, int y) {
    if(mop.find({x, y}) == mop.end())
        mop[ {x, y}] = mop.size();
    return mop[ {x, y}];
}
void dfs(int node1, int node2, int mat[][N]) {

    if(vis.find({node1, node2}) != vis.end())
        return ;
    vis.insert({node1, node2});
    //cout<<node1<<" "<<node2<<"\n";
    for(int i = 0; i < 26; i++) {
        if(!trie[node1][i] || !trie[node2][i])continue;
        int x = trie[node1][i], y = trie[node2][i];

        mat[get_ind(node1, node2)][get_ind(x, y)] = 1;
        dfs(x, y, mat);

        if(final_state[x]) {
            mat[get_ind(node1, node2)][get_ind(0, y)] = 1;
            dfs(0, y, mat);
        }
        if(final_state[y]) {
            mat[get_ind(node1, node2)][get_ind(x, 0)] = 1;
            dfs(x, 0, mat);
        }
        if(final_state[x] && final_state[y]) {
            mat[get_ind(node1, node2)][get_ind(0, 0)]++;
        }
    }
}
int main() {
    IO
    int n, m;
    cin >> n >> m;
    while(n--) {
        string s;
        cin >> s;
        insert(s);
    }
    int cur[N][N]={};
    get_ind(0, 0);
    dfs(0, 0, cur);

    power(cur, m);
    cout << cur[0][0];
}

#include <bits/stdc++.h>

using namespace std;
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
const int mod = 1e9 + 7;
struct Matrix
{

    std::vector<std::vector<int>> a;
    int row, col;
    Matrix(){};
    Matrix(int row, int col, int e = 0);
    Matrix operator+(const Matrix &x);
    Matrix operator-(const Matrix &x);
    Matrix operator*(const Matrix &x);
    Matrix operator!();
};
Matrix::Matrix(int row, int col, int e) : row(row), col(col)
{
    a.resize(row, vector<int>(col, 0));
    if (e == 1)
    {
        for (int i = 0; i < min(row, col); i++)
            a[i][i] = 1;
    }
}

Matrix Matrix::operator*(const Matrix &x)
{
    Matrix res(row, x.col);
    assert(col == x.row);
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < x.col; j++)
        {
            for (int k = 0; k < col; k++)
            {
                if (!a[i][k] || !x.a[k][j])
                    continue;
                res.a[i][j] = (res.a[i][j] + 1ll * a[i][k] * x.a[k][j] % mod) % mod;
            }
        }
    }
    return res;
}
Matrix qpow(Matrix a, int x)
{
    Matrix res(a.row, a.col, 1);
    while (x)
    {
        if (x & 1)
            res = res * a;
        a = a * a;
        x >>= 1;
    }
    return res;
}
struct DictionaryTree
{
    vector<vector<int>> son;
    vector<int> f;
    int scnt, rt;
    DictionaryTree(int n, int m)
    {
        rt = 0;
        scnt = 1;
        son.resize(n, vector<int>(m));
        f.resize(n);
    }
    void insert(string &s)
    {
        int tmp = rt;
        for (auto i : s)
        {
            if (!son[tmp][i - 'a'])
                son[tmp][i - 'a'] = scnt++;
            tmp = son[tmp][i - 'a'];
        }
        f[tmp] = 1;
    }
};

void solve()
{
    int n, m;
    cin >> n >> m;
    DictionaryTree t(n * 6, 26);
    for (int i = 0; i < n; i++)
    {
        string str;
        cin >> str;
        t.insert(str);
    }
    //exit(0);
    int tot = 0;
    vector<vector<int>> mp(t.scnt, vector<int>(t.scnt, -1));
    vector<vector<int>> vis(t.scnt, vector<int>(t.scnt, 0));
    auto calc = [&](int x, int y) {
        if (mp[x][y] == -1)
            return mp[x][y] = tot++;
        else
            return mp[x][y];
    };
    queue<pair<int, int>> q;
    vector<pair<int, int>> a;

    q.push({0, 0});
    vis[0][0] = 1;
    while (!q.empty())
    {
        auto [u, v] = q.front();
        q.pop();
        auto o = calc(u, v);
        for (int i = 0; i < 26; i++)
        {
            int uu = t.son[u][i];
            int vv = t.son[v][i];
            if (t.f[u] == 1 && vv)
            {
                a.push_back({o, calc(0, vv)});
                if (!vis[0][vv])
                    q.push({0, vv});
                vis[0][vv] = 1;
            }
            if (t.f[v] == 1 && uu)
            {
                a.push_back({o, calc(uu, 0)});
                if (!vis[uu][0])
                    q.push({uu, 0});
                vis[uu][0] = 1;
            }
            if (t.f[v] == 1 && t.f[u] == 1)
            {
                a.push_back({o, calc(0, 0)});
                vis[0][0] = 1;
            }
        }
        for (int i = 0; i < 26; i++)
            for (int j = 0; j < 26; j++)
            {
                int uu = t.son[u][i];
                int vv = t.son[v][j];
                if (uu && vv)
                {
                    a.push_back({o, calc(uu, vv)});
                    if (!vis[uu][vv])
                        q.push({uu, vv});
                    vis[uu][vv] = 1;
                }
            }
    }
    Matrix res(tot, tot);
    for (auto [u, v] : a)
    {
        res.a[u][v] = 1;
    }
    auto ans = qpow(res, m + 1);
    cout << ans.a[0][0] << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T = 1;

    while (T--)
    {
        solve();
    }
}

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

struct barrett {
    unsigned int _m;
    unsigned long long im;

    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {

        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#include <iostream>
#include <vector>
#include <array>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <functional>

template <int K, class T>
struct Trie {
    struct Node {
        std::array<int, K> nxt;
        bool end;
        explicit Node() : end(false) { nxt.fill(-1); }
    };

    std::vector<Node> nodes;
    std::function<int(T)> enc;

    explicit Trie(T base)
        : nodes(1), enc([=](T c) { return c - base; }) {}

    template <class Container>
    void add(const Container& s) {
        int pos = 0;
        for (T ci : s) {
            int c = enc(ci);

            int npos = nodes[pos].nxt[c];
            if (npos == -1) {
                npos = nodes.size();
                nodes[pos].nxt[c] = npos;
                nodes.emplace_back();
            }
            pos = npos;
        }
        nodes[pos].end = true;
    }

    template <class Container>
    int find(const Container& s) const {
        int pos = 0;
        for (char c : s) {
            int ci = enc(c);
            pos = nodes[pos].nxt[ci];
            if (pos == -1) return -1;
        }
        return pos;
    }

    Node& operator[](int pos) { return nodes[pos]; }
    Node operator[](int pos) const { return nodes[pos]; }
};

template <class T>
struct Matrix : public std::vector<std::vector<T>> {
    // constructor
    using std::vector<std::vector<T>>::vector;

    Matrix(int h, int w, T val = 0) {
        this->resize(h);
        for (auto& v : *this) v.resize(w, val);
    }

    static Matrix id(int n) {
        Matrix m(n, n);
        for (int i = 0; i < n; ++i) m[i][i] = 1;
        return m;
    }

    // arithmetic
    Matrix operator*(const Matrix& m) const { return Matrix(*this) *= m; }
    Matrix& operator*=(const Matrix& m) {
        int h1 = this->size(),
            h2 = m.size(),
            w2 = m.front().size();

        Matrix nmat(h1, w2);
        for (int i = 0; i < h1; ++i) {
            for (int j = 0; j < w2; ++j) {
                for (int k = 0; k < h2; ++k) {
                    nmat[i][j] += (*this)[i][k] * m[k][j];
                }
            }
        }
        return *this = nmat;
    }

    template <class U>
    Matrix pow(U k) {
        Matrix ret = id(this->size());
        Matrix a = *this;

        while (k > 0) {
            if (k & 1) ret *= a;
            a *= a;
            k >>= 1;
        }
        return ret;
    }
};

using namespace std;
using mint = atcoder::modint998244353;

void solve() {
    int m;
    Trie<26, char> trie('a');
    {
        int n;
        cin >> n >> m;

        while (n--) {
            string s;
            cin >> s;
            trie.add(s);
        }
    }

    map<pair<int, int>, int> enc;
    auto get = [&](int i, int j) {
        auto p = make_pair(i, j);
        if (enc.count(p)) {
            return enc[p];
        } else {
            int k = enc.size();
            return enc[p] = k;
        }
    };

    vector<pair<int, int>> es;
    {
        queue<pair<int, int>> que;
        que.emplace(0, 0);
        set<int> vis;

        while (!que.empty()) {
            auto [i, j] = que.front();
            que.pop();
            int u = get(i, j);

            if (vis.count(u)) continue;
            vis.insert(u);

            auto add_edge = [&](int ni, int nj) {
                int v = get(ni, nj);
                es.emplace_back(u, v);
                que.emplace(ni, nj);
            };

            for (int c = 0; c < 26; ++c) {
                if (trie[i].nxt[c] == -1 ||
                    trie[j].nxt[c] == -1) continue;

                int ni = trie[i].nxt[c],
                    nj = trie[j].nxt[c];

                add_edge(ni, nj);
                if (trie[ni].end) add_edge(0, nj);
                if (trie[nj].end) add_edge(ni, 0);
                if (trie[ni].end && trie[nj].end) add_edge(0, 0);
            }
        }
    }

    int n = enc.size();

    Matrix<mint> mat(n, n);
    for (auto [u, v] : es) mat[v][u] = 1;

    mat = mat.pow(m);
    cout << mat[0][0].val() << "\n";
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    solve();

    return 0;
}

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
constexpr LL mod = 998244353;
constexpr int maxn = 200;
struct Mat{
    LL A[maxn][maxn];
    Mat(){
        memset(A, 0, sizeof A);
    }
    Mat operator * (const Mat& mat)const{
        Mat res;
        for(int i = 0; i < maxn; i += 1)
            for(int j = 0; j < maxn; j += 1)
                for(int k = 0; k < maxn; k += 1)
                    res.A[i][j] = (res.A[i][j] + A[i][k] * mat.A[k][j]) % mod;
        return res;
    }
};
Mat power(Mat a, LL r){
    Mat res;
    for(int i = 0; i < maxn; i += 1) res.A[i][i] = 1;
    for(; r; r >>= 1, a = a * a)
        if(r & 1) res = res * a;
    return res;
}
int main(){
    cin.sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<string> vs(n);
    for(auto& s : vs) cin >> s;
    vector<int> shift(n + 1);
    for(int i = 1; i <= n; i += 1)
        shift[i] = shift[i - 1] + vs[i - 1].size() - 1;
    int f = shift.back(), k = (f + 1) * (f + 1);
    vector<vector<int>> G(k), H(k);
    auto tr = [&](int x, int y){
        if(x == f){
            for(int i = 0; i < n; i += 1)
                if(y == shift[i]) return vs[i][0];
            return '\0';
        }
        if(y == f){
            for(int i = 0; i < n; i += 1)
                if(x == shift[i + 1] - 1) return vs[i].back();
            return '\0';
        }
        for(int i = 0; i < n; i += 1)
            if(x + 1 == y and x >= shift[i] and y < shift[i + 1]) return vs[i][x - shift[i] + 1];
        return '\0';
    };
    for(int i = 0; i <= f; i += 1)
        for(int j = 0; j <= f; j += 1)
            for(int x = 0; x <= f; x += 1)
                for(int y = 0; y <= f; y += 1){
                    if(i == f and x == f and j == f and y == f){
                        for(int k = 0; k < n; k += 1)
                            if(vs[k].size() == 1) G[i * (f + 1) + j].push_back(x * (f + 1) + y);
                        continue;
                    }
                    if(i == f and x == f){
                        for(int k = 0; k < n; k += 1){
                            if(vs[k].size() == 1 and tr(j, y) == vs[k][0]) G[i * (f + 1) + j].push_back(x * (f + 1) + y);
                        }
                        continue;
                    }
                    if(j == f and y == f){
                        for(int k = 0; k < n; k += 1){
                            if(vs[k].size() == 1 and tr(i, x) == vs[k][0]) G[i * (f + 1) + j].push_back(x * (f + 1) + y);
                        }
                        continue;
                    }
                    int ti = tr(i, x), tj = tr(j, y);
                    if(ti and tj and ti == tj){
                        G[i * (f + 1) + j].push_back(x * (f + 1) + y);
                    }
                }
    for(int i = 0; i < k; i += 1)
        for(int j : G[i]) H[j].push_back(i);
    vector<int> vG(k), vH(k);
    function<void(vector<vector<int>>&, vector<int>&, int)> DFS = [&](vector<vector<int>>& G, vector<int>& vis, int u){
        vis[u] = 1;
        for(int v : G[u]) if(not vis[v]) DFS(G, vis, v);
    };
    DFS(G, vG, k - 1);
    DFS(H, vH, k - 1);
    map<int, int> mp;
    int id = 0;
    for(int i = 0; i < k; i += 1)
        if(vG[i] and vH[i]) mp[i] = id ++;
    //cout << id << "\n";
    assert(id <= maxn);
    Mat mat;
    for(int i = 0; i < k; i += 1) if(mp.count(i))
        for(int j : G[i]) if(mp.count(j)){
            mat.A[mp[j]][mp[i]] += 1;
        }
    Mat res = power(mat, m);
    cout << res.A[mp[k - 1]][mp[k - 1]] << '\n';
    return 0;
}

#include<bits/stdc++.h>
#define L(i, j, k) for(int i = j, i##E = k; i <= i##E; i++)
#define R(i, j, k) for(int i = j, i##E = k; i >= i##E; i--)
#define ll long long
#define pii pair<int, int>
#define db double
#define x first
#define y second
#define sz(a) ((int) (a).size())
#define mkp make_pair
#define vi vector<int>
using namespace std;
const int N = 407, mod = 998244353;
int all = 1, tot;
struct Martix {
	int G[N][N];
	void clear() { L(i, 1, tot) L(j, 1, tot) G[i][j] = 0; }
	void start() { clear(); L(i, 1, tot) G[i][i] = 1; }
} P;
Martix operator * (Martix aa, Martix bb) {
	Martix res;
	res.clear();
	L(i, 1, tot)
		L(j, 1, tot)
			L(k, 1, tot) (res.G[i][j] += (ll) aa.G[i][k] * bb.G[k][j] % mod) %= mod;
	return res;
}
Martix operator ^ (Martix aa, int bb)  {
	Martix res; res.start();
	for(; bb; aa = aa * aa, bb >>= 1) if(bb & 1) res = res * aa;
	return res;
}
int n, m, Len, ch[N][26], Cnt[N];
char s[N];
int Vis[N][N], f[N][2];
queue< int > q;
int get(int x, int y) {
	if(x > y) swap(x, y);
	if(!Vis[x][y]) Vis[x][y] = ++tot, f[tot][0] = x, f[tot][1] = y, q.push(tot);
	return Vis[x][y];
}
void getEdge() {
	get(1, 1);
	while( !q.empty() ) {
		int u = q.front(), s1 = f[u][0], s2 = f[u][1];
		q.pop();
		L(i, 0, 25) if(ch[s1][i] && ch[s2][i]) {
			P.G[u][get(ch[s1][i], ch[s2][i])] = 1;
			P.G[u][get(ch[s1][i], 1)] = Cnt[ch[s2][i]];
			P.G[u][get(1, ch[s2][i])] = Cnt[ch[s1][i]];
			P.G[u][get(1, 1)] = Cnt[ch[s1][i]] * Cnt[ch[s2][i]];
		}
	}
	if(tot > 300) assert(0);
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> m;
	L(i, 1, n) {
		cin >> (s + 1), Len = strlen(s + 1);
		int now = 1;
		L(j, 1, Len) {
			if(!ch[now][s[j] - 'a']) ch[now][s[j] - 'a'] = ++all;
			now = ch[now][s[j] - 'a'];
		}
		Cnt[now] ++;
	}
	getEdge();
	cout << (P ^ m).G[1][1] << "\n";
	return 0;
}
// To Cheat, To attack!

#include <bits/stdc++.h>
using namespace std;

const int MOD = 998244353;

typedef vector<int> row;
typedef vector<row> matrix;
inline int add(const int &a, const int &b) {
  int c = a + b;
  if (c >= MOD) c -= MOD;
  return c;
}
inline int mult(const int &a, const int &b) {
  return (long long)a * b % MOD;
}
matrix operator*(const matrix &m1, const matrix &m2) {
  int r = m1.size();
  int m = m1.back().size();
  int c = m2.back().size();
  matrix ret(r, row(c, 0));
  for (int i = 0; i < r; i++) {
    for (int k = 0; k < m; k++) {
      for (int j = 0; j < c; j++) {
        ret[i][j] = add(ret[i][j], mult(m1[i][k], m2[k][j]));
      }
    }
  }
  return ret;
}
matrix one(int dim) {
  matrix ret(dim, row(dim, 0));
  for (int i = 0; i < dim; i++) {
    ret[i][i] = 1;
  }
  return ret;
}
matrix operator^(const matrix &m, const int &e) {
  if (e == 0) return one(m.size());
  matrix sqrtm = m ^ (e / 2);
  matrix ret = sqrtm * sqrtm;
  if (e & 1) ret = ret * m;
  return ret;
}

struct Trie {
  int A = 26;
  int N;
  vector<vector<int>> next;
  vector<int> cnt;

  Trie() : N(0) {
    node();
  }

  int node() {
    next.emplace_back(A, -1);
    cnt.emplace_back(0);
    return N++;
  }

  inline int get(char c) {
    return c - 'a';
  }

  inline void insert(string s) {
    int cur = 0;
    for (char c : s) {
      int to = get(c);
      if (next[cur][to] == -1) next[cur][to] = node();
      cur = next[cur][to];
    }
    cnt[cur]++;
  }
};

const int N = 1605;
int id[N][N];
vector<vector<int>> to;
Trie trie;

void dfs(int i, int j) {
  if (i > j) swap(i, j);
  if (~id[i][j]) return;
  id[i][j] = to.size();
  to.emplace_back();

  vector<bool> one_end(trie.A, false);
  bool two_end = false;

  for (int c = 0; c < trie.A; c++) {
    int ni = trie.next[i][c];
    int nj = trie.next[j][c];

    if (~ni and ~nj) {
      dfs(ni, nj);
      to[id[i][j]].push_back(id[ni][nj]);
      if (trie.cnt[ni] or trie.cnt[nj]) one_end[c] = true;
      if (trie.cnt[ni] and trie.cnt[nj]) two_end = true;
    }
  }

  for (int c = 0; c < trie.A; c++) {
    if (one_end[c]) {
      int ni = trie.next[i][c];
      int nj = trie.next[j][c];
      if (trie.cnt[nj]) {
        dfs(0, ni);
        to[id[i][j]].push_back(id[0][ni]);
      }
      if (trie.cnt[ni]) {
        dfs(0, nj);
        to[id[i][j]].push_back(id[0][nj]);
      }
    }
  }
  if (two_end) {
    dfs(0, 0);
    to[id[i][j]].push_back(id[0][0]);
  }
}

int main() {
  int n, m;
  scanf("%d %d", &n, &m);

  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    trie.insert(s);
  }

  memset(id, -1, sizeof id);
  dfs(0, 0);

  int dim = to.size();
  matrix mat(dim, row(dim, 0));
  for (int i = 0; i < dim; i++) {
    for (int j : to[i]) {
      mat[i][j]++;
    }
  }

  mat = mat ^ m;

  printf("%d\n", mat[0][0]);

  return 0;
}

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
typedef long long llint;

const int MOD = 998244353;

int mod_add(int x, int y) { return (x + y) % MOD; }

int mod_sub(int x, int y) { return (x - y + MOD) % MOD; }

int mod_mult(int x, int y) { return static_cast<int>(llint(x) * y % MOD); }

int mod_pow(int x, int y) {
  int ret = 1;
  int curr = x, p = y;
  while (p != 0) {
    if (p & 1) {
      ret = mod_mult(ret, curr);
    }
    curr = mod_mult(curr, curr);
    p >>= 1;
  }
  return ret;
}

int mod_div(int x, int y) { return mod_mult(x, mod_pow(y, MOD - 2)); }

const int S = 1000;
const int A = 26;
struct Node {
  bool terminal;
  int next[A];
};
int ncnt;
Node nodes[S];

int n, m;
vector<string> words;
int res;

bool readin() {
  if (!(cin >> n >> m)) {
    return false;
  }
  words.resize(n);
  for (int i = 0; i < n; ++i) {
    cin >> words[i];
  }
  return true;
}

typedef vector<vector<int>> Matrix;

void matrix_copy(const Matrix &a, Matrix &b) {
  int n = a.size();
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      b[i][j] = a[i][j];
    }
  }
}

void matrix_mult(const Matrix &a, const Matrix &b, Matrix &c) {
  int n = a.size();
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      c[i][j] = 0;
      for (int k = 0; k < n; ++k) {
        c[i][j] = mod_add(c[i][j], mod_mult(a[i][k], b[k][j]));
      }
    }
  }
}

void matrix_pow(const Matrix &a, int r, Matrix &b) {
  int n = a.size();
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      b[i][j] = (i == j ? 1 : 0);
    }
  }
  Matrix a_copy = a;
  Matrix tmp(n, vector<int>(n));
  while (r > 0) {
    if (r % 2 != 0) {
      matrix_copy(b, tmp);
      matrix_mult(tmp, a_copy, b);
    }
    matrix_copy(a_copy, tmp);
    matrix_mult(tmp, tmp, a_copy);
    r /= 2;
  }
}

int allocate_node() {
  fill(nodes[ncnt].next, nodes[ncnt].next + A, -1);
  nodes[ncnt].terminal = false;
  return ncnt++;
}

void add_word(Node &root, const string &word) {
  Node *curr = &root;
  for (string::size_type i = 0; i < word.size(); ++i) {
    if (curr->next[word[i] - 'a'] == -1) {
      curr->next[word[i] - 'a'] = allocate_node();
    }
    curr = &nodes[curr->next[word[i] - 'a']];
  }
  curr->terminal = true;
}

void solve() {
  ncnt = 0;
  allocate_node();
  Node &root = nodes[0];
  for (const auto &word : words) {
    add_word(root, word);
  }
  queue<pair<int, int>> q;
  map<pair<int, int>, int> mp;
  set<int> terminate_states;
  set<pair<int, int>> transitions;
  q.push(make_pair(0, 0));
  mp[make_pair(0, 0)] = mp.size();
  while (!q.empty()) {
    auto s = q.front();
    q.pop();
    for (int a = 0; a < A; ++a) {
      int u = nodes[s.first].next[a], v = nodes[s.second].next[a];
      if (u == -1 || v == -1) {
        continue;
      }
      int tmp;
      if (mp.find(make_pair(u, v)) == mp.end()) {
        q.push(make_pair(u, v));
        tmp = mp[make_pair(u, v)] = mp.size();
        transitions.insert(make_pair(mp[s], tmp));
        if (nodes[u].terminal && nodes[v].terminal) {
          terminate_states.insert(tmp);
          transitions.insert(make_pair(mp[s], 0));
        }
      } else {
        tmp = mp[make_pair(u, v)];
        transitions.insert(make_pair(mp[s], tmp));
      }
      if (nodes[u].terminal) {
        if (mp.find(make_pair(0, v)) == mp.end()) {
          q.push(make_pair(0, v));
          tmp = mp[make_pair(0, v)] = mp.size();
          transitions.insert(make_pair(mp[s], tmp));
        } else {
          tmp = mp[make_pair(0, v)];
          transitions.insert(make_pair(mp[s], tmp));
        }
      }
      if (nodes[v].terminal) {
        if (mp.find(make_pair(u, 0)) == mp.end()) {
          q.push(make_pair(u, 0));
          tmp = mp[make_pair(u, 0)] = mp.size();
          transitions.insert(make_pair(mp[s], tmp));
        } else {
          tmp = mp[make_pair(u, 0)];
          transitions.insert(make_pair(mp[s], tmp));
        }
      }
    }
  }
  int N = mp.size();
  Matrix a(N, vector<int>(N));
  for (const auto &t : transitions) {
    a[t.second][t.first] = 1;
  }
  Matrix b(N, vector<int>(N));
  matrix_pow(a, m, b);
  res = 0;
  for (int i = 0; i < N; ++i) {
    if (terminate_states.find(i) != terminate_states.end()) {
      res = mod_add(res, b[i][0]);
    }
  }
  cout << res << endl;
}

int main() {
  while (readin()) {
    solve();
  }
  return 0;
}

// Exported by Exporter.exe

// Included from F.cpp
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define F first
#define S second
#define MP make_pair
#define MTP make_tuple
#define R Read
#define RD Read_Digit
#define RP Read_P
#define RL Read_Loop
#define RLD Read_Loop_Digit
#define RLP Read_Loop_P
#ifdef ONLINE_JUDGE
	#define Debug(x) ;
	#define Debugln(x) ;
	#define Debug_Array(n,x) ;
	#define Debugln_Array(n,x) ;
	#define NL ;
#else
	#define Debug(x) printf("%s :", (#x)); _Debug(x)
	#define Debugln(x) printf("%s :", (#x)); _Debugln(x)
	#define Debug_Array(n,x) printf("%s :", (#x)); _Debug_Array((n), (x))
	#define Debugln_Array(n,x) printf("%s :", (#x)); _Debugln_Array((n), (x))
	#define NL printf("\n")
#endif
typedef long long int ll;
typedef unsigned long long int ull;

constexpr int kN = 100;
constexpr int kMod = 998244353;
// constexpr int kMod = int(1E9 + 7);
// constexpr int kInf = 0x3f3f3f3f;
// constexpr ll kInf = 0x3f3f3f3f3f3f3f3f;
// constexpr double kPi = acos(-1);
// constexpr double kEps = 1E-9;

// Included from C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp
// --- Get ---
static inline char Get_Raw_Char() {
	static char buf[1 << 16], *p = buf, *end = buf;
	if (p == end) {
		if ((end = buf + fread(buf, 1, 1 << 16, stdin)) == buf) return '\0';
		p = buf;
	}
	return *p++;
}

// --- Read ---
template <typename T> static inline void Read_P(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	return ;
}

template <typename T> static inline void Read(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	if (neg) n = -n;
	return ;
}

template <typename T> static inline void Read_Digit(T &n) {
	static_assert(is_integral<T>::value);
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;
	n = int(c - '0');
	return ;
}

// --- Read multiple ---
template <typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read(n); return Read(Fargs...);}
template <typename T, typename... Targs> static inline void Read_Digit(T &n, Targs&... Fargs) {Read_Digit(n); return Read_Digit(Fargs...);}
template <typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P(n); return Read_P(Fargs...);}

// --- Read Loop ---
template <typename T> static inline void Read_Loop_i(int i, T *a) {return Read(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_i(int i, T *a, Targs*... Fargs) {Read(a[i]); return Read_Loop_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_Digit_i(int i, T *a) {return Read_Digit(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_Digit_i(int i, T *a, Targs*... Fargs) {Read_Digit(a[i]); return Read_Loop_Digit_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_Digit(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_Digit_i(i, Fargs...);}

template <typename T> static inline void Read_Loop_P_i(int i, T *a) {return Read_P(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_P_i(int i, T *a, Targs*... Fargs) {Read_P(a[i]); return Read_Loop_P_i(i, Fargs...);}
template <typename... Targs> static inline void Read_Loop_P(int n, Targs*... Fargs) {for (int i = 1; i <= n; i++) Read_Loop_P_i(i, Fargs...);}

// --- Float ---
template <int mul, typename T> static inline void Read(T &n) {
	char c;
	bool neg = false;
	while (!isdigit(c = Get_Raw_Char())) if (c == '-') neg = true;
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;

	if (neg) n = -n;
	return ;
}

template <int mul, typename T> static inline void Read_P(T &n) {
	char c;
	while (!isdigit(c = Get_Raw_Char())) ;

	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');

	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt++ < mul) n = n * 10;
	return ;
}

template <int mul, typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {Read<mul>(n); return Read<mul>(Fargs...);}
template <int mul, typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {Read_P<mul>(n); return Read_P<mul>(Fargs...);}

// --- init ---
inline void IOS() {ios::sync_with_stdio(false); cin.tie(0);}
inline void Freopen(const char *in, const char *out) {freopen(in, "r", stdin); freopen(out, "w", stdout);}

// --- Output ---
template <typename T> void Print(T x) {
	if (x < 0) {
		printf("-");
		x = -x;
	}
	if (x == 0) printf("0");
	else {
		static int val[100];
		int idx = -1;
		while (x) {
			val[++idx] = x % 10;
			x /= 10;
		}
		while (idx >= 0) printf("%d", val[idx--]);
	}
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp
template <typename T> inline void sort(vector<T> &v) {return sort(v.begin(), v.end());}
template <typename T> inline void sort_r(vector<T> &v) {return sort(v.begin(), v.end(), greater<T>());}

template <typename T> inline void reverse(vector<T> &v) {return reverse(v.begin(), v.end());}

template <typename T> inline void Merge(vector<T> &a, vector<T> &b, vector<T> &c) {
	if (c.size() < a.size() + b.size()) c.resize(a.size() + b.size());
	merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
	return ;
}

template <typename T> inline void Discrete(vector<T> &v) {sort(v); v.resize(unique(v.begin(), v.end()) - v.begin());}

template <typename T> using PQ = priority_queue<T>;
template <typename T> using PQ_R = priority_queue<T, vector<T>, greater<T>>;

template <typename T> inline T ABS(T n) {return n >= 0 ? n : -n;}
template <typename T> inline T gcd(T a, T b) {return b ? gcd(b, a % b) : a;}
template <typename T> inline T lcm(T a, T b) {return a * b / gcd(a, b);}
template <typename T, typename... Targs> inline T min(T a, T b, T c, Targs... args) {return min(a, min(b, c, args...));}
template <typename T, typename... Targs> inline T max(T a, T b, T c, Targs... args) {return max(a, max(b, c, args...));}
template <typename T> inline void chmin(T &a, T b) {a = min(a, b); return ;}
template <typename T> inline void chmax(T &a, T b) {a = max(a, b); return ;}
template <typename T, typename... Targs> inline void chmin(T &a, T b, T c, Targs... args) {a = min(a, min(b, c, args...)); return ;}
template <typename T, typename... Targs> inline void chmax(T &a, T b, T c, Targs... args) {a = max(a, max(b, c, args...)); return ;}

template <typename T> inline int Digit_Sum(T a) {
	int ans = 0;
	while (a) {
		ans += a % 10;
		a /= 10;
	}
	return ans;
}
template <typename T> inline int Num_Length(T a) {
	int ans = 1;
	while (a /= 10) ans++;
	return ans;
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp
void _print(int x) {printf("%d", x);}
void _print(long long int x) {printf("%lld", x);}
void _print(double x) {printf("%lf", x);}
template <typename T> void _print(T x) {return x.out();}
template <typename T1, typename T2> void _print(pair<T1, T2> x) {printf("("); _print(x.first); printf(", "); _print(x.second); printf(")");}

template <typename T> void _Debug(T x) {_print(x); printf("\n");}
template <typename T> void _Debug(vector<T> v) {
	if (v.empty()) printf(" empty");
	else for (T i : v) printf(" "), _print(i);
	printf("\n");
}

template <typename T1, typename T2, typename T3> void _Debug(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf(" ");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf(" ");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf(" ");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debug(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf(" ");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(vector<T> v) {
	if (v.empty()) printf(" empty\n");
	else {
		for (T i : v) printf("\n"), _print(i);
		printf("\n");
	}
}

template <typename T1, typename T2, typename T3> void _Debugln(priority_queue<T1, T2, T3> pq) {
	if (pq.empty()) printf(" empty");
	else {
		while (!pq.empty()) {
			printf("\n");
			_print(pq.top());
			pq.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(queue<T> q) {
	if (q.empty()) printf(" empty");
	else {
		while (!q.empty()) {
			printf("\n");
			_print(q.front());
			q.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(stack<T> st) {
	if (st.empty()) printf(" empty");
	else {
		while (!st.empty()) {
			printf("\n");
			_print(st.top());
			st.pop();
		}
	}
	printf("\n");
}

template <typename T> void _Debugln(deque<T> dq) {
	if (dq.empty()) printf(" empty");
	else {
		while (!dq.empty()) {
			printf("\n");
			_print(dq.front());
			dq.pop_front();
		}
	}
	printf("\n");
}

template <typename T> void _Debug_Array(int n, const T *x) {for (int i = 1; i <= n; i++) printf(" "), _print(x[i]); printf("\n");}
template <typename T> void _Debugln_Array(int n, const T *x) {printf("\n"); for (int i = 1; i <= n; i++) _print(x[i]), printf("\n");}
// End of C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp

// Included from C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp
template <typename T1, typename T2> T1 Pow(T1 a, T2 b) {
	T1 ans(1);
	while (b) {
		if (b & 1) ans *= a;
		a *= a;
		b >>= 1;
	}
	return ans;
}

template <int kMod> struct Mod_Int {
	constexpr static int Mod() {return kMod;}

	int val;
	Mod_Int() {val = 0;}
	template <typename T> Mod_Int(const T &x) {val = x;}
	template <int nMod> Mod_Int(const Mod_Int<nMod> &x) {val = x.val;}

	Mod_Int inv() const {return Pow(*this, kMod - 2);}

	Mod_Int operator + (const Mod_Int &x) const {
		Mod_Int ans(val + x.val);
		if (ans.val >= kMod) ans.val -= kMod;
		return ans;
	}
	Mod_Int operator - (const Mod_Int &x) const {
		Mod_Int ans(val - x.val);
		if (ans.val < 0) ans.val += kMod;
		return ans;
	}
	Mod_Int operator * (const Mod_Int &x) const {return Mod_Int(1LL * val * x.val % kMod);}
	Mod_Int operator / (const Mod_Int &x) const {return *this * x.inv();}
	Mod_Int operator ^ (const Mod_Int &x) const {return Pow(*this, x.val);}
	Mod_Int operator << (const int &x) const {return ((1LL * val) << x) % kMod;}

	Mod_Int operator += (const Mod_Int &x) {return *this = *this + x;}
	Mod_Int operator -= (const Mod_Int &x) {return *this = *this - x;}
	Mod_Int operator *= (const Mod_Int &x) {return *this = *this * x;}
	Mod_Int operator /= (const Mod_Int &x) {return *this = *this / x;}
	Mod_Int operator ^= (const Mod_Int &x) {return *this = Pow(*this, x.val);}
	Mod_Int operator <<= (const int &x) {return *this = *this << x;}

	Mod_Int operator ++(int) {
		val++;
		if (val >= kMod) val -= kMod;
		return *this;
	}
	Mod_Int operator --(int) {
		val--;
		if (val < 0) val += kMod;
		return *this;
	}

	bool operator < (const Mod_Int &x) const {return val < x.val;}
	bool operator > (const Mod_Int &x) const {return val > x.val;}
	bool operator <= (const Mod_Int &x) const {return val <= x.val;}
	bool operator >= (const Mod_Int &x) const {return val >= x.val;}
	bool operator == (const Mod_Int &x) const {return val == x.val;}
	bool operator != (const Mod_Int &x) const {return val != x.val;}

	void out() const {printf("%d", val);}
};

using Mint = Mod_Int<kMod>;

namespace Factorial {
	Mint *f, *inf;
	bool preprocessed_factorial;
	void Pre_Factorial(const int &sz) {
		if (preprocessed_factorial) return ;
		preprocessed_factorial = true;
		f = new Mint[sz + 1];
		inf = new Mint[sz + 1];
		f[0] = f[1] = inf[0] = inf[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		inf[sz] = f[sz].inv();
		for (int i = sz; i > 2; i--) inf[i - 1] = inf[i] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] * inf[m];}
	inline Mint C(const int &n, const int &m) {return f[n] * inf[m] * inf[n - m];}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] * inf[m] * inf[n - 1];}
	inline Mint Catalan(const int &n) {return f[n << 1] * inf[n] * inf[n + 1];}
}

namespace Factorial_No_Inf {
	Mint *f;
	void Pre_Factorial(const int &sz) {
		f = new Mint[sz + 1];
		f[0] = f[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] / f[m];}
	inline Mint C(const int &n, const int &m) {return f[n] / (f[m] * f[n - m]);}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] / (f[m] * f[n - 1]);}
	inline Mint Catalan(const int &n) {return f[n << 1] / (f[n] * f[n + 1]);}
}

namespace Inverse {
	using namespace Factorial;
	Mint *inv;
	void Pre_Inverse(const int &sz) {
		inv = new Mint[sz + 1];
		inv[1] = 1;
		Pre_Factorial(sz);
		for (int i = 1; i <= sz; i++) inv[i] = f[i - 1] * inf[i];
		return ;
	}
};
// End of C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp

struct Matrix {
	Mint val[kN][kN];
	int sz;

	Matrix() {}
	Matrix(int x, Mint v) {
		sz = x;
		for (int i = 0; i < sz; i++) for (int j = 0; j < sz; j++) val[i][j] = 0;
		for (int i = 0; i < sz; i++) val[i][i] = v;
	}

	Matrix operator * (Matrix b) const {
		Matrix ans(sz, Mint(0));
		for (int i = 0; i < sz; i++) for (int j = 0; j < sz; j++) for (int k = 0; k < sz; k++)
			ans.val[i][j] += val[i][k] * b.val[k][j];
		return ans;
	}
	Matrix operator *= (Matrix b) {return *this = *this * b;}
};

Matrix mPow(Matrix A, ll b) {
	Matrix ans(A.sz, Mint(1));
	while (b) {
		if (b & 1) ans *= A;
		A *= A;
		b >>= 1;
	}
	return ans;
}

string s[kN];
int idx[kN][kN][kN];
int len[kN];
Matrix A;

int main() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> s[i];

	for (int i = 1; i <= n; i++) len[i] = int(s[i].size());

	constexpr int kLen = 5;

	int cur = 0;
	// idx : lst s, len diff, wait

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 0; k < kLen; k++)
		idx[i][j][k] = cur++;

	for (int i = 0; i < kLen; i++) idx[0][0][i] = cur++;
	for (int i = 1; i <= n; i++) for (int k = 0; k < kLen; k++) idx[i][0][k] = idx[0][0][k];

	A = Matrix(cur, Mint(0));
	A.sz = cur;
	for (int i = 0; i < cur; i++) for (int j = 0; j < cur; j++) A.val[i][j] = 0;

	//printf("A:\n");
	//for (int i = 0; i < cur; i++, printf("\n")) for (int j = 0; j < cur; j++) printf(" %d", A.val[i][j]);

	for (int i = 1; i <= n; i++) {
		//printf("(0, 0, 0) to (0, 0, %d) ++\n", len[i] - 1);
		A.val[idx[0][0][len[i] - 1]][idx[0][0][0]]++;
	}

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k < kLen; k++)
		A.val[idx[i][j][k - 1]][idx[i][j][k]]++;

	for (int i = 1; i < kLen; i++) A.val[idx[0][0][i - 1]][idx[0][0][i]]++;

	auto match = [&](int x, int idx, int y, int idy, int len) -> bool {
		for (int i = 0; i < len; i++) if (s[x][idx + i] != s[y][idy + i]) return false;
		return true;
	};

	for (int i = 1; i <= n; i++) for (int j = 1; j < len[i]; j++) for (int k = 1; k <= n; k++) {
		int mn = min(j, len[k]);
		if (!match(i, len[i] - j, k, 0, mn)) continue;

		if (len[k] == j) {
			//printf("(%d, %d, 0) to (0, 0, %d) ++\n", i, j, j - 1);
			A.val[idx[0][0][j - 1]][idx[i][j][0]]++;
		}
		else if (len[k] < j) {
			//printf("(%d, %d, 0) to (%d, %d, %d) ++\n", i, j, i, j - len[k], len[k] - 1);
			A.val[idx[i][j - len[k]][len[k] - 1]][idx[i][j][0]]++;
		}
		else {
			//printf("(%d, %d, 0) to (%d, %d, %d) ++\n", i, j, k, len[k] - j, j - 1);
			A.val[idx[k][len[k] - j][j - 1]][idx[i][j][0]]++;
		}
	}

	for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) {
		int mn = min(len[i], len[j]);
		if (match(i, 0, j, 0, mn)) {
			if (len[i] < len[j]) {
				//printf("(0, 0, 0) to (%d, %d, %d) += 2\n", j, len[j] - len[i], mn - 1);
				A.val[idx[j][len[j] - len[i]][mn - 1]][idx[0][0][0]] += 2;
			}
			else {
				//printf("(0, 0, 0) to (%d, %d, %d) += 2\n", i, len[i] - len[j], mn - 1);
				A.val[idx[i][len[i] - len[j]][mn - 1]][idx[0][0][0]] += 2;
			}
			// len[i] != len[j]
		}
	}

	//printf("A:\n");
	//for (int i = 0; i < cur; i++, printf("\n")) for (int j = 0; j < cur; j++) printf(" %d", A.val[i][j]);
	A = mPow(A, m);

	//printf("A:\n");
	//for (int i = 0; i < cur; i++, printf("\n")) for (int j = 0; j < cur; j++) printf(" %d", A.val[i][j]);

	Mint ans;
	ans = A.val[idx[0][0][0]][idx[0][0][0]];
	printf("%d\n", ans);
}
// End of F.cpp

//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("fast-math")
//#pragma GCC optimize("profile-values,profile-reorder-functions,tracer")
//#pragma GCC optimize("move-loop-invariants")
//#pragma GCC optimize("unswitch-loops")
//#pragma GCC optimize("branch-target-load-optimize")
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
#define mt make_tuple
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long double ld;
const int MOD=998244353;
const int INF=0x3f3f3f3f;
const ll INFll=0x3f3f3f3f3f3f3f3fll;
const double EPS=1e-6;
namespace fastio{
	#define FILE_SIZE 1<<23
	char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
	inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
	inline void putc(char x){(*p3++=x);}
	template<typename T> void read(T &x){
		x=0;char c=getchar();T neg=0;
		while(!isdigit(c)) neg|=(c=='-'),c=getchar();
		while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
		if(neg) x=-x;
	}
	template<typename T> void recursive_print(T x){
		if(!x) return;
		recursive_print(x/10);putc(x%10+'0');
	}
	template<typename T> void print(T x){
		if(!x) putc('0');if(x<0) putc('-'),x=-x;
		recursive_print(x);
	}
	template<typename T> void print(T x,char c){print(x);putc(c);}
	void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
template<typename Tv,int limN,int limM> struct link_list{
	int hd[limN+5],nxt[limM+5],item_n=0;Tv val[limM+5];
	void clear(){memset(hd,0,sizeof(hd));item_n=0;}//be aware of the TC of memset
	void ins(int x,Tv y){val[++item_n]=y;nxt[item_n]=hd[x];hd[x]=item_n;}
};
const int MAXN=8;
const int MAXP=41;
const int MAXL=5;
const int MAXS=215;
int n,m,ch[MAXP+5][27],ncnt=1,tot,ed[MAXP+5];
string s[MAXN+2];
void insert(string str){
	int cur=1;
	for(int i=0;i<str.size();i++){
		if(!ch[cur][str[i]-'a']) ch[cur][str[i]-'a']=++ncnt;
		cur=ch[cur][str[i]-'a'];
	} ed[cur]=1;
}
struct mat{
	u64 a[MAXS+5][MAXS+5];
	mat(){memset(a,0,sizeof(a));}
	mat operator *(const mat &rhs){
		mat res;
		for(int i=1;i<=tot;i++) for(int k=1;k<=tot;k++) for(int j=1;j<=tot;j++){
			res.a[i][j]+=a[i][k]*rhs.a[k][j];
			if((j&15)==0) res.a[i][j]%=MOD;
		}
		for(int i=1;i<=tot;i++) for(int j=1;j<=tot;j++) res.a[i][j]%=MOD;
		return res;
	}
	void print(){
		for(int i=1;i<=tot;i++) for(int j=1;j<=tot;j++)
			printf("%llu%c",a[i][j]," \n"[j==tot]);
	}
} trs,res;
int a[MAXL+2][MAXP+5][MAXP+5];
void dfsclc(int p,int id,int len,int ori){
	if(ed[p]&&len!=0) dfsclc(1,id,len,ori);
	if(len==s[id].size()) return a[len][ori][p]++,void();
	if(ch[p][s[id][len]-'a']) dfsclc(ch[p][s[id][len]-'a'],id,len+1,ori);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		static char orzczx[MAXL+4];
		scanf("%s",orzczx+1);int len=strlen(orzczx+1);
		for(int j=1;j<=len;j++) s[i].pb(orzczx[j]);
		insert(s[i]);
	} tot=ncnt*5;
	for(int i=1;i<=ncnt;i++) for(int j=1;j<=n;j++) dfsclc(i,j,0,i);
	for(int i=1;i<=4;i++) for(int j=1;j<=ncnt;j++) trs.a[j+i*ncnt][j+(i-1)*ncnt]=1;
	for(int i=1;i<=5;i++) for(int j=1;j<=ncnt;j++) for(int k=1;k<=ncnt;k++)
		trs.a[(5-i)*ncnt+j][4*ncnt+k]=a[i][j][k];
//	trs.print();
	for(int i=1;i<=tot;i++) res.a[i][i]=1;
	for(;m;m>>=1,trs=trs*trs) if(m&1) res=res*trs;
	printf("%d\n",res.a[4*ncnt+1][4*ncnt+1]);
	return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <ctype.h>
#include <deque>
#include <cstring>
#include <set>
#include <bitset>
#include <map>
#include <chrono>
#include <random>
#include <unordered_map>
#include <stdio.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef std::vector<int> vi;
typedef std::vector<bool> vb;
typedef std::vector<string> vs;
typedef std::vector<double> vd;
typedef std::vector<long long> vll;
typedef std::vector<std::vector<int> > vvi;
typedef vector<vll> vvll;
typedef std::vector<std::pair<int, int> > vpi;
typedef vector<vpi> vvpi;
typedef std::pair<int, int> pi;
typedef std::pair<ll, ll> pll;
typedef std::vector<pll> vpll;

const long long mod = 998244353 ;
const unsigned gen_seed = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937_64 gen(gen_seed);

#define all(c) (c).begin(),(c).end()
#define srt(c) sort(all(c))
#define srtrev(c) sort(all(c)); reverse(all(c))
#define forn(i, a, b) for(int i = a; i < b; i++)
#define read(x) scanf("%d", &x)
#define readv(x, n) vi x(n); forn(i,0,n) scanf("%d", &x[i])

#define pb push_back
#define mp make_pair
vs a;
int valid[9][9][5][5];
int k;

vvll mul(const vvll & x, const vvll & y) {
    vvll res(k, vll(k, 0));
    forn(i,0,k) forn(j,0,k) {
        forn(p,0,k) res[i][j] += x[i][p] * y[p][j] % mod;
        res[i][j] %= mod;
    }
    return res;
}

vll mulv(const vvll & x, const vll & y) {
    vll res(k,0);
    forn(i,0,k) {
        forn(p,0,k) res[i] += x[i][p] * y[p] % mod;
        res[i] %= mod;
    }
    return res;
}

vvll mpow(vvll & x, int k) {
    if(k == 1) return x;
    vvll u = mpow(x, k/2);
    vvll res = mul(u, u);
    if(k%2) res = mul(res, x);
    return res;
}

int main()
{
#ifdef LOCAL
    freopen("input.txt", "rt", stdin);
    freopen("output.txt", "wt", stdout);
#endif
    int n,m;
    scanf("%d %d\n", &n, &m);
    a.pb(string(1,'#'));
    char c[100];
    forn(i,0,n) {
        scanf("%s", c);
        a.pb(string(c));
    }
    forn(i,1,n+1) {
        forn(j,1,n+1) {
            forn(p1,0,a[i].size()) {
                forn(p2,0,a[j].size()) {
//                    if(p1+1 == a[i].size() && p2+1==a[j].size()) continue;
                    int can = 1;
                    for(int k = -4; k<=4; k++) {
                        if(p1+k>=0 && p1+k<a[i].size() && p2+k>=0 && p2+k<a[j].size() && a[i][p1+k] != a[j][p2+k]) can = 0;
                    }
                    if(can) {
                        valid[i][j][p1][p2] = 1;
//                        if(p1 + 1 != a[i].size() && p2 + 1 != a[j].size()) valid[i][j][p1][p2] = 1;
//                        else if(p1+1==a[i].size()) {
//                            valid[0][j][0][p2] = 1;
//                        }
//                        else if(p2+1==a[j].size()) {
//                            valid[i][0][p1][0] = 1;
//                        }
                    }
                }
            }
        }
    }
    vvi state;
    state.pb(vi(4,0));
    forn(i,0,n+1)
        forn(j,0,n+1)
            forn(p1,0,a[i].size())
                forn(p2,0,a[j].size())
                    if(valid[i][j][p1][p2]) state.pb(vi({i,j,p1,p2}));
    map<vi, int> code;
    forn(i,0,state.size()) code[state[i]] = i;
    k = state.size();
//    vector<set<int>> g(k);
    vvll mat(k, vll(k, 0));
    forn(f,0,k) {
        int i = state[f][0];
        int j = state[f][1];
        int p1 = state[f][2];
        int p2 = state[f][3];
        p1++;
        p2++;
        if(p1 == a[i].size()) {
            p1 = 0;
            i = 0;
        }
        if(p2 == a[j].size()) {
            p2 = 0;
            j = 0;
        }
        if (i!=0 && j!=0) {
//            g[f].insert(code[vi({i,j,p1,p2})]);
            mat[code[vi({i,j,p1,p2})]][f]++;
        }
        else if(i==0 && j==0) {
            forn(i2,1,n+1) forn(j2,1,n+1) {
                int can = 1;
                int pt = 0;
                while(pt<a[i2].size() && pt<a[j2].size()) {
                    if(a[i2][pt] != a[j2][pt]) can = 0;
                    pt++;
                }
                if(can) {
                    int p12 = 0;
                    int p22 = 0;
                    int i3 = i2;
                    int j3 = j2;
//                    g[f].insert(code[vi({i3,j3,p12,p22})]);
                    mat[code[vi({i3,j3,p12,p22})]][f]++;
                }
            }
        }
        else if(i == 0) {
            forn(i2,1,n+1) {
                int can = 1;
                int pt = 0;
                while(pt<a[i2].size() && p2+pt < a[j].size()) {
                    if(a[i2][pt] != a[j][p2+pt]) can = 0;
                    pt++;
                }
                if(can) {
                    int i3 = i2;
                    int j3 = j;
                    int p12 = 0;
                    int p22 = p2;
//                    g[f].insert(code[vi({i3,j3,p12,p22})]);
                    mat[code[vi({i3,j3,p12,p22})]][f]++;
                }
            }
        }
        else if(j == 0) {
            forn(j2,1,n+1) {
                int can = 1;
                int pt = 0;
                while(pt<a[j2].size() && p1+pt < a[i].size()) {
                    if(a[j2][pt] != a[i][p1+pt]) can = 0;
                    pt++;
                }
                if(can) {
                    int i3 = i;
                    int j3 = j2;
                    int p12 = p1;
                    int p22 = 0;
//                    g[f].insert(code[vi({i3,j3,p12,p22})]);
                    mat[code[vi({i3,j3,p12,p22})]][f]++;
                }
            }
        }
    }

//    forn(i,0,k) for(auto x : g[i]) mat[x][i] = 1;
    vvi g(k);
    forn(i,0,k) forn(j,0,k) if(mat[i][j] > 0) g[j].pb(i);
    vi vis(k, 0);
    vi q;
    q.pb(0);
    vis[0] = 1;
    while(!q.empty()) {
        int v = q.back();
        q.pop_back();
        for(auto u : g[v]) if(vis[u] == 0) {
            vis[u] = 1;
            q.pb(u);
        }
    }
    vi comp;
    forn(i,0,k) if(vis[i]) comp.pb(i);
    int kwas = k;
    int k = comp.size();
    vvll compmat(k, vll(k, 0));
    forn(i,0,k) forn(j,0,k) compmat[i][j] = mat[comp[i]][comp[j]];
    vvll res = mpow(mat, m);
    vll d(k,0);
    d[0] = 1;
    vll ans = mulv(res, d);
    ll fin = 0;
    forn(ff,0,k) {
        int f = comp[ff];
        int i = state[f][0];
        int j = state[f][1];
        int p1 = state[f][2];
        int p2 = state[f][3];
        if(p1+1 == a[i].size()) {
            p1 = 0;
            i = 0;
        }
        if(p2+1 == a[j].size()) {
            p2 = 0;
            j = 0;
        }
        if(i == 0 && j == 0) fin += ans[f];
    }
    cout<<fin%mod;

}

#include <bits/stdc++.h>
using namespace std;
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define loop(i, a) for (int i = 0; i < (a); ++i)
#define cont(i, a) for (int i = 1; i <= (a); ++i)
#define circ(i, a, b) for (int i = (a); i <= (b); ++i)
#define range(i, a, b, c) for (int i = (a); (c) > 0 ? i <= (b) : i >= (b); i += (c))
#define parse(it, x) for (auto &it : (x))
#define pub push_back
#define pob pop_back
#define emb emplace_back
#define mak make_pair
#define mkt make_tuple
typedef long long ll;
typedef long double lf;
const int Inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;

const int jt = 998244353;
void inline add(int &a, int b) { a += b - jt; a += (a >> 31) & jt; }
void inline sub(int &a, int b) { a -= b; a += (a >> 31) & jt; }
void inline mul(int &a, int b) { a = (ll)a * b % jt; }
int inline Add(int a, int b) { return a + b >= jt ? a + b - jt : a + b; }
int inline Sub(int a, int b) { return a - b < 0 ? a - b + jt : a - b; }
int inline Mul(int a, int b) { return (ll)a * b % jt; }

int n, m, t;
char s[9][9];
vector<pair<int, int> > lss;
map<pair<int, int>, int> ids;
int son[44][26], nds;
bool fin[44];
string ss[44];

void dfs(int now) {
	loop(i, 26) if (son[now][i]) {
		ss[son[now][i]] = ss[now] + (char)(i + 'a');
		dfs(son[now][i]);
	}
}

struct Matrix {
	int a[500][500];
	Matrix(int x = 0) {
		loop(i, 500) loop(j, 500) a[i][j] = (i == j ? x : 0);
	}
	Matrix operator * (const Matrix &mat) const {
		static Matrix res;
		loop(i, t) loop(j, t) res.a[i][j] = 0;
		loop(i, t) loop(j, t) loop(k, t) add(res.a[i][k], Mul(a[i][j], mat.a[j][k]));
		return res;
	}
} tr;

Matrix ksmii(Matrix a, int b) {
	Matrix ans(1);
	while (b) {
		if (b & 1) ans = ans * a;
		a = a * a; b >>= 1;
	}
	return ans;
}

int main() {
	scanf("%d%d", &n, &m);
	nds = 1;
	cont(i, n) {
		scanf("%s", s[i]); int len = strlen(s[i]);
		int now = 1;
		loop(j, len) {
			if (!son[now][s[i][j] - 'a']) son[now][s[i][j] - 'a'] = ++nds;
			now = son[now][s[i][j] - 'a'];
		}
		fin[now] = 1;
	}
	dfs(1);
	cont(i, nds) cont(j, nds) {
		if (SZ(ss[j]) > SZ(ss[i])) continue;
		bool can = 1;
		loop(k, SZ(ss[j])) if (ss[j][k] != ss[i][SZ(ss[i]) - SZ(ss[j]) + k]) can = 0;
		if (!can) continue;
		ids[mak(i, j)] = SZ(lss);
		lss.emb(i, j);
	}
	t = SZ(lss);
	loop(i, t) {
		int a, b; tie(a, b) = lss[i];
		loop(c, 26) if (son[a][c] && son[b][c]) {
			++tr.a[i][ids[mak(son[a][c], son[b][c])]];
		}
		loop(j, t) {
			int c, d; tie(c, d) = lss[j];
			if (fin[c]) add(tr.a[i][ids[mak(d, 1)]], tr.a[i][j]);
			if (fin[d]) add(tr.a[i][ids[mak(c, 1)]], tr.a[i][j]);
			if (fin[c] && fin[d]) add(tr.a[i][0], tr.a[i][j]);
		}
	}
	tr = ksmii(tr, m);
	printf("%d\n", tr.a[0][0]);
	return 0;
}

#include <iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#include<ctime>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<bitset>
#define sqr(x) ((x)*(x))
#define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
#define fd1(i,n) for ((i)=(n);(i)>=1;(i)--)
#define fz0g(i,n) for ((i)=0;(i)<=(n);(i)++)
#define fd0g(i,n) for ((i)=(n);(i)>=0;(i)--)
#define fz0k(i,n) for ((i)=0;(i)<(n);(i)++)
#define fd0k(i,n) for ((i)=(long long)((n)-1);(i)>=0;(i)--)
#define fz(i,x,y) for ((i)=(x);(i)<=(y);(i)++)
#define fd(i,y,x) for ((i)=(y);(i)>=(x);(i)--)
#define fzin fz1(i,n)
#define fzim fz1(i,m)
#define fzjn fz1(j,n)
#define fzjm fz1(j,m)
#define ff(c,itr) for (__typeof((c).begin()) itr=(c).begin();itr!=(c).end();++itr)
#define rdst(st,len){static char ss[len];scanf(" %s",ss);(st)=ss;}
#define incm(x,y) {x=((x)+(y))%mod;}
#define spln(i,n) (i==n?'\n':' ')
#define fac_init(n){fac[0]=fac[1]=inv[1]=fi[0]=fi[1]=1;fz(i,2,n){fac[i]=1ll*fac[i-1]*i%mod;inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;fi[i]=1ll*fi[i-1]*inv[i]%mod;}}
#define fi first
#define se second
#define mk make_pair
using namespace std;
inline void read(int &x)
{
	char c;int f=1;
	while(!isdigit(c=getchar()))if(c=='-')f=-1;
	x=(c&15);while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);
	x*=f;
}
const int mod=998244353;
const long long mod2=1ll*mod*mod;
int n,m,i,j,k,cnt=1,ch[45][26],ed[45];
int a[1005][1005],b[1005][1005];
long long c[1005][1005];
string st;
int id[45][45],cid;
void dfs(int x,int y)
{
	if(x>y){
		id[x][y]=id[y][x];
		return;
	}
	if(id[x][y]) return;
	id[x][y]=++cid;
	if(ed[x]) dfs(1,y);
	if(ed[y]) dfs(x,1);
	int i;
	fz0k(i,26)if(ch[x][i]&&ch[y][i])dfs(ch[x][i],ch[y][i]);
}
int main()
{
	cin>>n>>m;
	while(n--){
		cin>>st;
		int x=1;
		fz0k(i,st.size()){
			if(!ch[x][st[i]-'a']){
				ch[x][st[i]-'a']=++cnt;
			}
			x=ch[x][st[i]-'a'];
		}
		ed[x]++;
	}
	dfs(1,1);
	int x,y;
	fz1(x,cnt)fz1(y,cnt)if(x<=y&&id[x][y]){
		fz0k(i,26)if(ch[x][i]&&ch[y][i]){
			a[id[x][y]][id[ch[x][i]][ch[y][i]]]+=1;
			a[id[x][y]][id[ch[x][i]][1]]+=ed[ch[y][i]];
			a[id[x][y]][id[1][ch[y][i]]]+=ed[ch[x][i]];
			a[id[x][y]][id[1][1]]+=ed[ch[x][i]]*ed[ch[y][i]];
		}
	}
	cerr<<cid<<endl;
//	fz1(x,cnt)fz1(y,cnt)fz1(i,cnt)fz1(j,cnt)if(a[id[x][y]][id[i][j]]){
//		cerr<<x<<' '<<y<<' '<<i<<' '<<j<<' '<<a[id[x][y]][id[i][j]]<<endl;
//	}
	fz1(i,cid) b[i][i]=1;
	while(m){
		if(m&1){
			fz1(i,cid)fz1(j,cid){
				c[i][j]=0;
				fz1(k,cid){
					c[i][j]=(c[i][j]+1ll*a[i][k]*b[k][j]);
					if(c[i][j]>=mod2)c[i][j]-=mod2;
				}
			}
			fz1(i,cid)fz1(j,cid){
				b[i][j]=c[i][j]%mod;
			}
		}
		m/=2;
		fz1(i,cid)fz1(j,cid){
			c[i][j]=0;
			fz1(k,cid){
				c[i][j]=(c[i][j]+1ll*a[i][k]*a[k][j]);
				if(c[i][j]>=mod2)c[i][j]-=mod2;
			}
		}
		fz1(i,cid)fz1(j,cid){
			a[i][j]=c[i][j]%mod;
		}
	}
	cout<<b[id[1][1]][id[1][1]]<<endl;
	return 0;
}

#include <bits/stdc++.h>
typedef unsigned long long ull;
typedef long long ll;
#define inf 0x3f3f3f3f
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define nep(i, r, l) for (int i = r; i >= l; i--)
void sc(int &x) { scanf("%d", &x); }
void sc(int &x, int &y) { scanf("%d%d", &x, &y); }
void sc(int &x, int &y, int &z) { scanf("%d%d%d", &x, &y, &z); }
void sc(ll &x) { scanf("%lld", &x); }
void sc(ll &x, ll &y) { scanf("%lld%lld", &x, &y); }
void sc(ll &x, ll &y, ll &z) { scanf("%lld%lld%lld", &x, &y, &z); }
void sc(char *x) { scanf("%s", x); }
void sc(char *x, char *y) { scanf("%s%s", x, y); }
void sc(char *x, char *y, char *z) { scanf("%s%s%s", x, y, z); }
void out(int x) { printf("%d\n", x); }
void out(ll x) { printf("%lld\n", x); }
void out(int x, int y) { printf("%d %d\n", x, y); }
void out(ll x, ll y) { printf("%lld %lld\n", x, y); }
void out(int x, int y, int z) { printf("%d %d %d\n", x, y, z); }
void out(ll x, ll y, ll z) { printf("%lld %lld %lld\n", x, y, z); }
void ast(ll x,ll l,ll r){assert(x>=l&&x<=r);}
using namespace std;
const int N=205,mod=998244353;
/*
 ----x
---
dp[len][i][j][5]
长度为len，提示1为第i个单词并且提示1在位置len，提示2在位置len-j,转移到len剩余的步数
len 1～1e9
i 1～8
j 0～4

dp[len][i][j]->dp[len+x][s][k]

a graph,find the number a roads so that the tot length is m
//x<=5

\sum_{i=0}^{n-1} dp[m][i][0][0]
*/
void add(int &x,int y)
{
  x+=y;if(x>=mod) x-=mod;
}
struct node
{
  int a[201][201];
  node(){memset(a,0,sizeof(a));}
  node operator*(const node&o)const
  {
    node ans;
    for(int i=0;i<=200;i++)
      for(int j=0;j<=200;j++)
      for(int k=0;k<=200;k++)
      add(ans.a[i][j],1ll*a[i][k]*o.a[k][j]%mod);
    return ans;
  }
};
node qpow(node a,int n)
{
  node ans;
  for(int i=0;i<=200;i++) ans.a[i][i]=1;
  for(;n;n>>=1,a=a*a)
  if(n&1) ans=ans*a;
  return ans;
}
int tot,ids,id[42][5];
string f[42];
int n,m,p[8];
string s[8];
map<string,int>mp,vis;
bool ispre(string a,string b)
{
  for(int i=0;i<a.size();i++) if(a[i]!=b[i]) return false;
  return true;
}
int ways(string a,string b)
{
  string hs=a+"#"+b;
  if(mp.count(hs)) return mp[hs];
  string str=a+b;
  int dp[20];
  memset(dp,0,sizeof(dp));
  dp[0]=1;
  rep(i,0,str.size())
  {
    rep(j,0,n-1)
    if(i+s[j].size()<=str.size()&&(i!=0||s[j].size()>a.size()))
    {
      bool flag=true;
      for(int k=0;k<s[j].size();k++)
        if(s[j][k]!=str[i+k]) flag=false;
      if(flag) dp[i+s[j].size()]=(dp[i+s[j].size()]+dp[i])%mod;
    }
  }
  return mp[hs]=dp[str.size()];
}
void sol(int cas)
{
  sc(n,m);
  rep(i,0,n-1) cin>>s[i];
  vis[""]=0;f[0]="";
  rep(i,0,n-1)
  {
    string t="";
    rep(j,0,s[i].size()-1)
    {
      t+=s[i][j];
      if(!vis[t]) vis[t]=++tot,f[tot]=t;
    }
  }
  node A;
  rep(i,0,tot)
    rep(j,0,4) id[i][j]=ids++;
  rep(i,0,tot)
  {
    rep(j,1,4) add(A.a[id[i][j]][id[i][j-1]],1);
    rep(j,0,n-1)
    {
      string t="",tt=s[j];
      for(int k=0;k<s[j].size();k++)
      {
        t+=tt[0];
        tt.erase(0,1);
        if(vis.count(tt))
          add(A.a[id[i][0]][id[vis[tt]][s[j].size()-1]],ways(f[i],t));
      }
      if(vis.count(f[i]+s[j]))
        add(A.a[id[i][0]][id[vis[f[i]+s[j]]][s[j].size()-1]],1);
    }
  }
  A=qpow(A,m);
  out(A.a[id[0][0]][id[0][0]]);
}
int main()
{
  // freopen("1.in", "r",stdin);
  // freopen("1.out", "w", stdout);
  srand(time(0));
  int t=1,cas=0;
  // scanf("%d",&t);
  while(t--)
  {
    sol(++cas);
  }
}
/*
befor submit code check:
freopen
size of N
mod
debug output
*/

// Sometimes, the questions are complicated - and the answers are simple. //
#pragma GCC optimize ("O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
#pragma GCC optimize ("unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define ld  long double
#define IO ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int mod = 998244353;
const int N = 205;
int res[N][N];
void mul(int a[][N], int b[][N]) {

    memset(res, 0, sizeof res);

    for(int i = 0; i < N; i++)
        for(int k = 0; k < N; k++)
            if(a[i][k])
                for(int j = 0; j < N; j++)
                    res[i][j] = (1LL * a[i][k] * b[k][j] + res[i][j]) % mod;

    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++)
            a[i][j] = res[i][j];
}
void power(int temp[][N], int p) {

    int res[N][N] = {0};
    for(int i = 0; i < N; i++)
        res[i][i] = 1;

    while(p) {
        if(p & 1)
            mul(res, temp);
        mul(temp, temp);
        p >>= 1;
    }

    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++)
            temp[i][j] = res[i][j];
}
int n, m ;
int trie[50][30], node_ind;
bool final_state[50];
void insert(string & s) {
    int node = 0;
    for(auto i : s) {
        int cur = i - 'a';
        if(!trie[node][cur])
            trie[node][cur] = ++node_ind;
        node = trie[node][cur];
    }
    final_state[node] = true;
}
map<pair<int, int>, int >mop;
set<pair<int, int> > vis;
int get_ind(int x, int y) {
    if(mop.find({x, y}) == mop.end())
        mop[ {x, y}] = mop.size();
    return mop[ {x, y}];
}
void dfs(int node1, int node2, int mat[][N]) {

    if(vis.find({node1, node2}) != vis.end())
        return ;
    vis.insert({node1, node2});
    //cout<<node1<<" "<<node2<<"\n";
    for(int i = 0; i < 26; i++) {
        if(!trie[node1][i] || !trie[node2][i])continue;
        int x = trie[node1][i], y = trie[node2][i];

        mat[get_ind(node1, node2)][get_ind(x, y)] = 1;
        dfs(x, y, mat);

        if(final_state[x]) {
            mat[get_ind(node1, node2)][get_ind(0, y)] = 1;
            dfs(0, y, mat);
        }
        if(final_state[y]) {
            mat[get_ind(node1, node2)][get_ind(x, 0)] = 1;
            dfs(x, 0, mat);
        }
        if(final_state[x] && final_state[y]) {
            mat[get_ind(node1, node2)][get_ind(0, 0)]++;
        }
    }
}
int main() {
    IO
    int n, m;
    cin >> n >> m;
    while(n--) {
        string s;
        cin >> s;
        insert(s);
    }
    int cur[N][N] = {};
    get_ind(0, 0);
    dfs(0, 0, cur);

    power(cur, m);
    cout << cur[0][0];
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 8 + 5;
const int MAXL = 5 + 5;
const int mod = 998244353;

inline void add_mod(int &a,int b){ a+=b; if(a>=mod) a-=mod;}

inline ll pw(ll a,ll b)
{
	ll res = 1;
	while(b)
	{
		if(b&1) res=res*a%mod;
		a=a*a%mod; b>>=1;
	}
	return res;
}

vector<int> Berlekamp_Massey(const vector<int> &a)
{
	int n = (int)a.size(), len = 0, m = 0, ld = 1;
	vector<int> res(n), lst(n), tmp;
	res[0] = lst[0] = 1;
	for(int i=0; i<n; ++i)
	{
		++m;
		int d = a[i];
		for(int j=1; j<=len; ++j) d = (d + (ll)res[j] * a[i - j]) %mod;
		if(!d) continue;
		tmp = res;
		ll mul = d * pw(ld, mod - 2) %mod;
		for(int j=m; j<n; ++j) res[j] = (res[j] - mul * lst[j - m]) %mod;
		if((len << 1) > i) continue;
		len = i + 1 - len;
		ld = d; lst = tmp; m = 0;
	}

	res.resize(len+1);
	res.erase(res.begin());
	for(int i=0; i<(int)res.size(); ++i) add_mod(res[i] = -res[i], mod);
	return res;
}

namespace Linear_Rec
{
	inline vector<int> combine(const vector<int> &a,const vector<int> &b,const vector<int> &tr)
	{
		vector<int> res((int)a.size() + (int)b.size() - 1);
		for(int i=0; i<(int)a.size(); ++i)
			for(int j=0; j<(int)b.size(); ++j)
				res[i+j] = (res[i+j] + (ll)a[i] * b[j]) %mod;
		for(int i=(int)res.size()-1; i>=(int)tr.size(); --i)
			for(int j=0; j<(int)tr.size(); ++j)
				add_mod(res[i - j - 1], (ll)res[i] * tr[j] %mod);
		res.resize(tr.size());
		return res;
	}
}

inline int linear_rec(const vector<int> &s,const vector<int> &tr,int k)
{
	using namespace Linear_Rec;

	int n = (int)tr.size();
	vector<int> res(n), a(n);
	res[0] = a[1] = 1;
	while(k)
	{
		if(k&1) res=combine(res,a,tr);
		a=combine(a,a,tr); k>>=1;
	}

	int ans = 0;
	for(int i=0; i<(int)tr.size(); ++i)
		ans = (ans + (ll)res[i] * s[i]) %mod;
	return ans;
}

char s[MAXN][MAXL];
int len[MAXN];

const int lim = 1e2;
const int LIM = lim + 5;

int f[LIM][MAXN][MAXL];
vector< pair<int,pii> > to[MAXN][MAXL];

inline bool chk_suf(int x,int l,int y)
{
	for(int i=len[x]-l+1, j=1; i<=len[x] && j<=len[y]; ++i, ++j)
		if(s[x][i] != s[y][j]) return 0;
	return 1;
}

inline pair<int,pii> get_nxt(int x,int xl,int y,int yl)
{
	if(xl == yl)
		return make_pair(xl, make_pair(0, 0));
	else if(xl < yl)
		return make_pair(xl, make_pair(y, yl - xl));
	else
		return make_pair(yl, make_pair(x, xl - yl));
}

int main(void)
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; ++i)
		scanf("%s",s[i]+1), len[i] = strlen(s[i] + 1);

	for(int i=1; i<=n; ++i)
		for(int j=1; j<len[i]; ++j)
			for(int k=1; k<=n; ++k) if(chk_suf(i,j,k))
				to[i][j].push_back(get_nxt(i, j, k, len[k]));

	for(int i=1; i<=n; ++i)
		for(int j=1; j<=n; ++j) if(chk_suf(i,len[i],j))
			to[0][0].push_back(get_nxt(i, len[i], j, len[j]));

	f[0][0][0] = 1;
	for(int i=0; i<lim; ++i)
		for(int j=0; j<=n; ++j)
		{
			int kl = j? 1: 0, kr = j? len[j]-1: 0;
			for(int k=kl; k<=kr; ++k) if(f[i][j][k])
			{
				vector< pair<int,pii> > &vec = to[j][k];
				for(int it=0; it<(int)vec.size(); ++it)
				{
					int ii = i + vec[it].first, jj = vec[it].second.first, kk = vec[it].second.second;
					if(ii < lim)
						add_mod(f[ii][jj][kk], f[i][j][k]);
				}
			}
		}
	vector<int> g(lim);
	for(int i=0; i<lim; ++i) g[i] = f[i][0][0];

	printf("%d",linear_rec(g, Berlekamp_Massey(g), m));
	return 0;
}

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int read()
{
	int ret=0;bool f=0;char c=getchar();
	while(c>'9'||c<'0')f|=(c=='-'),c=getchar();
	while(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+(c^48),c=getchar();
	return f?-ret:ret;
}
const int maxn=160;
const int mod=998244353;
int n,m;
map<pair<int,int>,int>id;
struct matrix
{
	int num[maxn][maxn];
	matrix(){memset(num,0,sizeof num);}
	matrix operator *(const matrix &x)
	{
		matrix ret;
		for(int i=0;i<id.size();i++)
			for(int j=0;j<id.size();j++)
				for(int k=0;k<id.size();k++)
					(ret.num[i][j]+=(ll)num[i][k]*x.num[k][j]%mod)%=mod;
		return ret;
	}
	friend matrix qpow(matrix a,int b)
	{
		matrix ret;for(int i=0;i<id.size();i++)ret.num[i][i]=1;
		for(;b;b>>=1,a=a*a)if(b&1)ret=ret*a;
		return ret;
	}
}tran,ans;
struct trie
{
	#define S(u,i) t[u].ch[i]
	struct node{int ch[26];bool ed;}t[maxn];int cnt;
	void insert(string &s)
	{
		int p=0;
		for(char &c:s)
		{
			if(!S(p,c-'a'))S(p,c-'a')=++cnt;
			p=S(p,c-'a');
		}
		t[p].ed=1;
	}
	void dfs(int u1,int u2)
	{
		if(u1>u2)swap(u1,u2);
		if(id.count({u1,u2}))return;
		if(u1&&u2){int tmp=id.size();id[{u1,u2}]=tmp;}
		for(int i=0;i<26;i++)
			if(S(u1,i)&&S(u2,i))dfs(S(u1,i),S(u2,i));
	}
	void getid(){for(int i=0;i<=cnt;i++)dfs(0,i);}
	void getmat()
	{
		for(auto &i:id)
		{
			int x=i.first.first,y=i.first.second;
			for(int j=0;j<26;j++)
				if(S(x,j)&&S(y,j))
				{
					int tox=S(x,j),toy=S(y,j);
					if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
				}
			if(t[x].ed)
				for(int j=0;j<26;j++)
					if(S(0,j)&&S(y,j))
					{
						int tox=S(0,j),toy=S(y,j);
						if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
					}
			if(t[y].ed&&x!=y)
				for(int j=0;j<26;j++)
					if(S(x,j)&&S(0,j))
					{
						int tox=S(x,j),toy=S(0,j);
						if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
					}
			if(t[x].ed&&t[y].ed)
				for(int j=0;j<26;j++)
					if(S(0,j)&&S(0,j))
					{
						int tox=S(0,j),toy=S(0,j);
						if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
					}
			if(x!=y)
			{
				swap(x,y);
				for(int j=0;j<26;j++)
				if(S(x,j)&&S(y,j))
				{
					int tox=S(x,j),toy=S(y,j);
					if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
				}
				if(t[x].ed)
					for(int j=0;j<26;j++)
						if(S(0,j)&&S(y,j))
						{
							int tox=S(0,j),toy=S(y,j);
							if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
						}
				if(t[y].ed&&x!=y)
					for(int j=0;j<26;j++)
						if(S(x,j)&&S(0,j))
						{
							int tox=S(x,j),toy=S(0,j);
							if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
						}
				if(t[x].ed&&t[y].ed)
					for(int j=0;j<26;j++)
						if(S(0,j)&&S(0,j))
						{
							int tox=S(0,j),toy=S(0,j);
							if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
						}
			}
		}
		for(int i=0;i<26;i++)
			if(S(0,i))ans.num[0][id[{S(0,i),S(0,i)}]]++;
	}
	#undef S
}tr;
int f[maxn];
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;i++){string s;cin>>s;tr.insert(s);}
	tr.getid();tr.getmat();
	ans=ans*qpow(tran,m-1);
	int sum=0;
	for(auto &i:id)
		if(tr.t[i.first.first].ed&&tr.t[i.first.second].ed)
			sum=((ll)sum+(1+(i.first.first!=i.first.second))*ans.num[0][i.second])%mod;
	printf("%d\n",sum);
	return 0;
}

#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
const int mod=998244353;
const int M=59;
int n,m,sz,tot;
int c[M][26];
int tag[M],vis[M][M];
char t[10];
struct Matrix{
	int a[M][M];
	void clear(){
		for(int i=1;i<=tot;++i)
		for(int j=1;j<=tot;++j)
			a[i][j]=0;
	}
	Matrix operator * (const Matrix&o){
		Matrix rex;rex.clear();
		for(int i=1;i<=tot;++i)
		for(int j=1;j<=tot;++j)
		for(int k=1;k<=tot;++k)
			rex.a[i][j]=(rex.a[i][j]+1ll*a[i][k]*o.a[k][j]%mod)%mod;
		return rex;
	}
}x,y;
void ins(char *s){
	int len=strlen(s+1),u=0;
	for(int i=1;i<=len;++i){
		int v=s[i]-'a'+1;
		if(!c[u][v])c[u][v]=++sz;
		u=c[u][v];
		if(i==len)tag[u]=1;
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%s",t+1);
		ins(t);
	}
	queue<pii>q;
	q.push(pii{0,0});
	vis[0][0]=++tot;
	x.clear();
	y.clear();
	for(int i=1;i<=tot;++i)y.a[i][i]=1;
	while(!q.empty()){
		pii u=q.front();
		q.pop();
		for(int i=1;i<=26;++i){
			pii v=pii{c[u.fi][i],c[u.se][i]};
			if(v.fi&&v.se&&!vis[v.fi][v.se]){
				vis[v.fi][v.se]=++tot;
				q.push(v);
				x.a[vis[u.fi][u.se]][vis[v.fi][v.se]]=1;
				if(tag[v.fi]){
					if(!vis[0][v.se])vis[0][v.se]=++tot,q.push(pii{0,v.se});
					x.a[vis[u.fi][u.se]][vis[0][v.se]]=1;
				}
				if(tag[v.se]){
					if(!vis[v.fi][0])vis[v.fi][0]=++tot,q.push(pii{v.fi,0});
					x.a[vis[u.fi][u.se]][vis[v.fi][0]]=1;
				}
				if(tag[v.fi]&&tag[v.se]){
					x.a[vis[u.fi][u.se]][vis[0][0]]=1;
				}
			}
		}
	}
	for(;m;m>>=1,x=x*x)if(m&1)y=y*x;
	printf("%d\n",y.a[1][1]);
	return 0;
}

#include<cstdio>//jzm yyds!!
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#define ll long long
#define MAXN 10005
#define uns unsigned
#define INF 0x3f3f3f3f
#define MOD 998244353ll
#define lowbit(x) ((x)&(-(x)))
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return f?x:-x;
}
struct matrix{
	int n,m;
	ll c[100][100];
	matrix(){memset(c,0,sizeof(c)),n=m=0;}
	matrix operator*(const matrix&a){
		matrix r;r.n=n,r.m=a.m;
		for(int i=1;i<=r.n;i++)
			for(int k=1;k<=m;k++)
				for(int j=1;j<=r.m;j++)
					r.c[i][j]=(r.c[i][j]+c[i][k]*a.c[k][j])%MOD;
		return r;
	}
};
matrix mpow(matrix a,ll b){
	matrix res;res.n=res.m=a.n;
	for(int i=1;i<=res.n;i++)res.c[i][i]=1;
	for(;b;b>>=1){
		if(b&1)res=res*a;
		a=a*a;
	}
	return res;
}
int n,m,t[50][30],mp[MAXN],IN,k;
bool op[50],ct[MAXN];
matrix a,b;
inline void instr(){
	int p=0,c;
	char s=getchar();
	while((s<'a'||s>'z')&&s>0)s=getchar();
	while(s>='a'&&s<='z'){
		c=s-'a';
		if(!t[p][c])t[p][c]=++IN;
		p=t[p][c],s=getchar();
	}
	op[p]=1;
}
inline int dfs(int u,int v){
	if(mp[u*100+v]>0)return mp[u*100+v];
	mp[u*100+v]=++b.n,b.m++,ct[b.n]=(op[u]&op[v]);
	int x=mp[u*100+v],y,c,d;
	for(int i=0;i<26;i++){
		if(op[u]&&t[0][i]){
			if(op[v]){
				c=t[0][i],d=t[0][i];
				y=dfs(c,d);
				b.c[x][y]=1;
			}
			if(t[v][i]){
				c=t[0][i],d=t[v][i];
				y=dfs(c,d),b.c[x][y]=1;
			}
		}
		if(t[u][i]){
			if(op[v]&&t[0][i]){
				c=t[u][i],d=t[0][i];
				y=dfs(c,d),b.c[x][y]=1;
			}
			if(t[v][i]){
				c=t[u][i],d=t[v][i];
				y=dfs(c,d),b.c[x][y]=1;
			}
		}
	}
	return x;
}
signed main()
{
	n=read(),m=read();
	for(int i=1;i<=n;i++)instr();
	for(int i=0;i<26;i++)if(t[0][i])dfs(t[0][i],t[0][i]);
	a.n=1,a.m=b.n;
	for(int i=0;i<26;i++)
		if(t[0][i]){
			int u=t[0][i],x=mp[u*100+u];
			a.c[1][x]=1;
		}
	a=a*mpow(b,m-1);
	ll ans=0;
	for(int i=1;i<=a.m;i++)if(ct[i])ans=(ans+a.c[1][i])%MOD;
	printf("%d\n",a.m);
	printf("%lld\n",ans);
	return 0;
}

#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(100, 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 = matXmat(res, A, M);
        }
        A = matXmat(A, A, M);
        n >>= 1;
    }
    return res;
}

class Solution {
public:
    long long solve(vector<string>& S, int m) {
        int n = S.size();

        int N = 1 << 6;
        auto isEnd = [&](int x) {
            int p = x & 7;
            x >>= 3;
            if (S[x].length() == p) {
                return true;
            }
            return false;
        };

        vector<vector<bool>> visited(N, vector<bool>(N, false));
        vector<pair<int,int>> que;

        vector<vector<bool>> ok(N, vector<bool>(N, false));

        vector<vector<vector<pair<int,int>>>> nexts(N, vector<vector<pair<int,int>>>(N));

        vector<pair<int,int>> srcs;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (S[i][0] == S[j][0]) {
                    int a = i << 3 | 1;
                    int b = j << 3 | 1;
                    que.emplace_back(a, b);
                    visited[a][b] = true;
                    srcs.emplace_back(a, b);
                }
            }
        }

        for (int i = 0; i < que.size(); ++i) {
            int a = que[i].first;
            int b = que[i].second;
            int pa = a & 7;
            int pb = b & 7;
            a >>= 3;
            b >>= 3;

            if (pa == S[a].length()) {
                if (pb == S[b].length()) {
                    ok[a][b] = true;
                    // cout << a << "," << pa << " :: " << b << "," << pb << endl;
                    for (auto& p : srcs) {
                        int na = p.first, nb = p.second;
                        nexts[a << 3 | pa][b << 3 | pb].emplace_back(na, nb);
                    }
                } else {
                    for (int i = 0; i < n; ++i) {
                        if (S[i][0] == S[b][pb]) {
                            int na = i << 3 | 1;
                            int nb = b << 3 | (pb + 1);
                            nexts[a << 3 | pa][b << 3 | pb].emplace_back(na, nb);
                            if (!visited[na][nb]) {
                                visited[na][nb] = true;
                                que.emplace_back(na, nb);
                            }
                        }
                    }
                }
            } else if (pb == S[b].length()) {
                for (int i = 0; i < n; ++i) {
                    if (S[i][0] == S[a][pa]) {
                        int na = a << 3 | (pa + 1);
                        int nb = i << 3 | 1;
                        nexts[a << 3 | pa][b << 3 | pb].emplace_back(na, nb);
                        if (!visited[na][nb]) {
                            visited[na][nb] = true;
                            que.emplace_back(na, nb);
                        }
                    }
                }
            } else {
                if (S[a][pa] == S[b][pb]) {
                    int na = a << 3 | (pa + 1);
                    int nb = b << 3 | (pb + 1);
                    nexts[a << 3 | pa][b << 3 | pb].emplace_back(na, nb);
                    if (!visited[na][nb]) {
                        visited[na][nb] = true;
                        que.emplace_back(na, nb);
                    }
                }
            }
        }

        while (true) {
            int chgs = 0;
            for (auto& p : que) {
                int a = p.first, b = p.second;
                if (ok[a][b]) {
                    continue;
                }
                for (auto& p2 : nexts[a][b]) {
                    int na = p2.first;
                    int nb = p2.second;
                    if (ok[na][nb]) {
                        ok[a][b] = true;
                        ++chgs;
                        break;
                    }
                }
            }
            if (chgs == 0) {
                break;
            }
        }

        map<pair<int,int>,int> indices;
        for (auto& p : que) {
            int a = p.first, b = p.second;
            if (ok[a][b]) {
                // cout << "ok " << a << " " << b << endl;
                int x = indices.size();
                indices[p] = x;
            }
        }

        int sz = indices.size();

        vector<vector<int>> mat(sz, vector<int>(sz, 0));
        for (auto& p : indices) {
            int u = p.second;
            for (auto& p2 : nexts[p.first.first][p.first.second]) {
                int v = indices[p2];
                mat[v][u] += 1;
            }
        }

        vector<int> A(sz, 0);
        for (auto& p : srcs) {
            int a = p.first;
            int b = p.second;
            if (ok[a][b]) {
                int u = indices[p];
                A[u] = 1;
            }
        }
        // cout << "sz " << sz << endl;

        --m;

        auto M = matPow(mat, m);
        auto ans = matXvec(M, A);

        long long res = 0;
        for (auto& p : indices) {
            int a = p.first.first;
            int b = p.first.second;
            int u = p.second;
            if (isEnd(a) && isEnd(b)) {
                res += ans[u];
            }
        }
        res %= MOD;
        return res;
    }
};

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;
}

#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 200005, S = 1000, M = 20;

int n, m;
int u[N];

struct ban
{
    int i;
    int l, r;
};
bool operator<(const ban& a, const ban& b)
{
    if (a.l / S < b.l / S)
        return true;
    if (a.l / S > b.l / S)
        return false;
    if ((a.l / S) % 2)
        return a.r < b.r;
    return a.r > b.r;
}

int k;
ban b[N];

int yans;
int z;
int t[N * 30][2];
int q[N * 30];

void ave(int x)
{
    yans ^= x;
    int pos = 0;
    for (int i = 0; i < M; ++i)
    {
        int u = !!(x & (1 << i));
        if (!t[pos][u])
            t[pos][u] = ++z;
        pos = t[pos][u];
        q[pos] ^= 1;
    }
}

void han(int x)
{
    ave(x);
}

void pp()
{
    int pos = 0;
    for (int i = 0; i < M; ++i)
    {
        yans ^= ((1 << i) * q[t[pos][0]]);
        yans ^= ((1 << i) * q[t[pos][1]]);
        swap(t[pos][0], t[pos][1]);
        pos = t[pos][0];
        if (!pos)
            break;
    }
}

void mm()
{
    int pos = 0;
    for (int i = 0; i < M; ++i)
    {
        yans ^= ((1 << i) * q[t[pos][0]]);
        yans ^= ((1 << i) * q[t[pos][1]]);
        swap(t[pos][0], t[pos][1]);
        pos = t[pos][1];
        if (!pos)
            break;
    }
}

char ans[N];

void solv()
{
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
    {
        int x;
        cin >> x;
        u[x] ^= 1;
    }

    cin >> k;
    for (int i = 0; i < k; ++i)
    {
        b[i].i = i;
        cin >> b[i].l >> b[i].r;
    }
    sort(b, b + k);

    int l = 1, r = 0;
    for (int i = 0; i < k; ++i)
    {
        while (r < b[i].r)
        {
            ++r;
            if (u[r])
                ave(r - l);
        }
        while (l > b[i].l)
        {
            --l;
            pp();
            if (u[l])
                ave(0);
        }
        while (r > b[i].r)
        {
            if (u[r])
                han(r - l);
            --r;
        }
        while (l < b[i].l)
        {
            if (u[l])
                han(0);
            mm();
            ++l;
        }
        if (yans)
            ans[b[i].i] = 'A';
        else
            ans[b[i].i] = 'B';
    }

    cout << ans << "\n";
}

int main()
{
    #ifdef SOMETHING
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    #endif // SOMETHING
    ios_base::sync_with_stdio(false), cin.tie(0);

    int tt = 1;
    //cin >> tt;
    while (tt--)
    {
        solv();
    }
    return 0;
}

#include<bits/stdc++.h>
#define N 251
#define mod 998244353
using namespace std;
typedef long long ll;
int n,m,tot=1,f[N][N],l,r,son[N*30][26],cnt,vis[N];
char str[N];
struct Node{int pos,x,y;}q[N*N];
inline int Mod(int x){return x>=mod?x-mod:x;}
inline int qpow(int a,int b){int res=1;while(b){if(b&1)res=1ll*res*a%mod;a=1ll*a*a%mod;b>>=1;}return res;}
struct Matrix{
	ll a[N][N];
	Matrix(){memset(a,0,sizeof a);}
	ll *operator [](int k){return a[k];}
	inline void Set(void){int i;for(i=1;i<=cnt;++i)a[i][i]=1;}
}ans;
inline Matrix operator*(Matrix a,Matrix b){
	int i,j,k;Matrix c;
	for(i=1;i<=cnt;++i)
		for(k=1;k<=cnt;++k)if(a[i][k]){
			for(j=1;j<=cnt;++j)c[i][j]+=a[i][k]*b[k][j];
			if((k%18)==0)for(j=1;j<=cnt;++j)c[i][j]%=mod;
		}
	for(i=1;i<=cnt;++i)for(j=1;j<=cnt;++j)c[i][j]%=mod;
	return c;
}
inline Matrix operator^(Matrix a,int k){
	Matrix res;res.Set();
	while(k){if(k&1)res=res*a;a=a*a;k>>=1;}
	return res;
}
inline int C(int&x){return !x?x=++tot:x;}
inline void Insert(void){
	int i,l=strlen(str+1),x=1;
	for(i=1;i<=l;++i)x=C(son[x][str[i]-'a']);
	vis[x]=1;
}
inline int F(int x,int y){if(x>y)swap(x,y);return !f[x][y]?(q[++r]={f[x][y]=++cnt,x,y},f[x][y]):f[x][y];}
signed main(void){
	int i,x,y,a,b;Node t;scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i)scanf("%s",str+1),Insert();
	l=1,r=0,F(1,1);
	while(l<=r){
		x=(t=q[l++]).x,y=t.y;
		for(i=0;i<26;++i)if((a=son[x][i])&&(b=son[y][i])){++ans[t.pos][F(a,b)];if(vis[a])++ans[t.pos][F(1,b)];;if(vis[b])++ans[t.pos][F(a,1)];;if(vis[a]&&vis[b])++ans[t.pos][F(1,1)];}
	}ans=ans^m;
	printf("%lld\n",ans[1][1]);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
namespace my_std{
	#define ll long long
	#define bl bool
	ll my_pow(ll a,ll b,ll mod){
		ll res=1;
		if(!b) return 1;
		while(b){
			if(b&1) res=(res*a)%mod;
			a=(a*a)%mod;
			b>>=1;
		}
		return res;
	}
	ll qpow(ll a,ll b){
		ll res=1;
		if(!b) return 1;
		while(b){
			if(b&1) res*=a;
			a*=a;
			b>>=1;
		}
		return res;
	}
	#define db double
	#define pf printf
	#define pc putchar
	#define fr(i,x,y) for(register ll i=(x);i<=(y);i++)
	#define pfr(i,x,y) for(register ll i=(x);i>=(y);i--)
	#define go(u) for(ll i=head[u];i;i=e[i].nxt)
	#define enter pc('\n')
	#define space pc(' ')
	#define fir first
	#define sec second
	#define MP make_pair
	#define il inline
	#define inf 8e18
	#define random(x) rand()*rand()%(x)
	#define inv(a,mod) my_pow((a),(mod-2),(mod))
	il ll read(){
		ll sum=0,f=1;
		char ch=0;
		while(!isdigit(ch)){
			if(ch=='-') f=-1;
			ch=getchar();
		}
		while(isdigit(ch)){
			sum=sum*10+(ch^48);
			ch=getchar();
		}
		return sum*f;
	}
	il void write(ll x){
		if(x<0){
			x=-x;
			pc('-');
		}
		if(x>9) write(x/10);
		pc(x%10+'0');
	}
	il void writeln(ll x){
		write(x);
		enter;
	}
	il void writesp(ll x){
		write(x);
		space;
	}
}
using namespace my_std;
#define mod 998244353
ll n,m,ch[55][26],rt=1,tot=1,mp[55][55],cnt=0;
bl ed[55],ck[55][55];
char s[11];
struct matrix{
	ll a[220][220];
	void clr(){
		fr(i,1,cnt) fr(j,1,cnt) a[i][j]=0;
	}
	void one(){
		clr();
		fr(i,1,cnt) a[i][i]=1;
	}
	matrix operator*(const matrix &x){
		matrix res;
		res.clr();
		fr(i,1,cnt) fr(j,1,cnt) fr(k,1,cnt) res.a[i][j]=(res.a[i][j]+a[i][k]*x.a[k][j]%mod)%mod;
		return res;
	}
}P,A;
il ll getid(ll x,ll y){
	if(x>y) swap(x,y);
	if(!mp[x][y]) mp[x][y]=++cnt;
	return mp[x][y];
}
void dfs(ll x,ll y){
	if(ck[x][y]||x>y) return;
	ck[x][y]=1;
	fr(i,0,25){
		if(!ch[x][i]||!ch[y][i]) continue;
		A.a[getid(x,y)][getid(ch[x][i],ch[y][i])]++;
		dfs(ch[x][i],ch[y][i]);
		if(ed[ch[x][i]]){
			A.a[getid(x,y)][getid(rt,ch[y][i])]++;
			dfs(rt,ch[y][i]);
		}
		if(ed[ch[y][i]]){
			A.a[getid(x,y)][getid(ch[x][i],rt)]++;
			dfs(ch[x][i],rt);
		}
		if(ed[ch[x][i]]&&ed[ch[y][i]]){
			A.a[getid(x,y)][getid(rt,rt)]++;
			dfs(rt,rt);
		}
	}
}
matrix mpow(matrix x,ll y){
	matrix res;
	res.one();
	while(y){
		if(y&1) res=res*x;
		x=x*x;
		y>>=1;
	}
	return res;
}
int main(){
	n=read();
	m=read();
	fr(i,1,n){
		scanf("%s",s+1);
		ll len=strlen(s+1),x=rt;
		fr(j,1,len){
			if(!ch[x][s[j]-'a']) ch[x][s[j]-'a']=++tot;
			x=ch[x][s[j]-'a'];
		}
		ed[x]=1;
	}
	mp[rt][rt]=++cnt;
	dfs(rt,rt);
	P.a[1][1]=1;
	P=P*mpow(A,m);
	write(P.a[1][1]);
}

#include <bits/stdc++.h>
using namespace std;
using lint = long long;
using pint = pair<int, int>;
using plint = pair<lint, lint>;
struct fast_ios { fast_ios(){ cin.tie(nullptr), ios::sync_with_stdio(false), cout << fixed << setprecision(20); }; } fast_ios_;
#define ALL(x) (x).begin(), (x).end()
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define IFOR(i, begin, end) for(int i=(end)-1,i##_begin_=(begin);i>=i##_begin_;i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)
template <typename T, typename V>
void ndarray(vector<T>& vec, const V& val, int len) { vec.assign(len, val); }
template <typename T, typename V, typename... Args> void ndarray(vector<T>& vec, const V& val, int len, Args... args) { vec.resize(len), for_each(begin(vec), end(vec), [&](T& v) { ndarray(v, val, args...); }); }
template <typename T> bool chmax(T &m, const T q) { if (m < q) {m = q; return true;} else return false; }
template <typename T> bool chmin(T &m, const T q) { if (m > q) {m = q; return true;} else return false; }
int floor_lg(long long x) { return x <= 0 ? -1 : 63 - __builtin_clzll(x); }
template <typename T1, typename T2> pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first + r.first, l.second + r.second); }
template <typename T1, typename T2> pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first - r.first, l.second - r.second); }
template <typename T> vector<T> sort_unique(vector<T> vec) { sort(vec.begin(), vec.end()), vec.erase(unique(vec.begin(), vec.end()), vec.end()); return vec; }
template <typename T> istream &operator>>(istream &is, vector<T> &vec) { for (auto &v : vec) is >> v; return is; }
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) { os << '['; for (auto v : vec) os << v << ','; os << ']'; return os; }
template <typename T, size_t sz> ostream &operator<<(ostream &os, const array<T, sz> &arr) { os << '['; for (auto v : arr) os << v << ','; os << ']'; return os; }
#if __cplusplus >= 201703L
template <typename... T> istream &operator>>(istream &is, tuple<T...> &tpl) { std::apply([&is](auto &&... args) { ((is >> args), ...);}, tpl); return is; }
template <typename... T> ostream &operator<<(ostream &os, const tuple<T...> &tpl) { std::apply([&os](auto &&... args) { ((os << args << ','), ...);}, tpl); return os; }
#endif
template <typename T> ostream &operator<<(ostream &os, const deque<T> &vec) { os << "deq["; for (auto v : vec) os << v << ','; os << ']'; return os; }
template <typename T> ostream &operator<<(ostream &os, const set<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T, typename TH> ostream &operator<<(ostream &os, const unordered_set<T, TH> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T> ostream &operator<<(ostream &os, const multiset<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T> ostream &operator<<(ostream &os, const unordered_multiset<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &pa) { os << '(' << pa.first << ',' << pa.second << ')'; return os; }
template <typename TK, typename TV> ostream &operator<<(ostream &os, const map<TK, TV> &mp) { os << '{'; for (auto v : mp) os << v.first << "=>" << v.second << ','; os << '}'; return os; }
template <typename TK, typename TV, typename TH> ostream &operator<<(ostream &os, const unordered_map<TK, TV, TH> &mp) { os << '{'; for (auto v : mp) os << v.first << "=>" << v.second << ','; os << '}'; return os; }
#ifdef HITONANODE_LOCAL
const string COLOR_RESET = "\033[0m", BRIGHT_GREEN = "\033[1;32m", BRIGHT_RED = "\033[1;31m", BRIGHT_CYAN = "\033[1;36m", NORMAL_CROSSED = "\033[0;9;37m", RED_BACKGROUND = "\033[1;41m", NORMAL_FAINT = "\033[0;2m";
#define dbg(x) cerr << BRIGHT_CYAN << #x << COLOR_RESET << " = " << (x) << NORMAL_FAINT << " (L" << __LINE__ << ") " << __FILE__ << COLOR_RESET << endl
#else
#define dbg(x) (x)
#endif

template <int mod> struct ModInt {
#if __cplusplus >= 201402L
#define MDCONST constexpr
#else
#define MDCONST
#endif
    using lint = long long;
    MDCONST static int get_mod() { return mod; }
    static int get_primitive_root() {
        static int primitive_root = 0;
        if (!primitive_root) {
            primitive_root = [&]() {
                std::set<int> fac;
                int v = mod - 1;
                for (lint i = 2; i * i <= v; i++)
                    while (v % i == 0) fac.insert(i), v /= i;
                if (v > 1) fac.insert(v);
                for (int g = 1; g < mod; g++) {
                    bool ok = true;
                    for (auto i : fac)
                        if (ModInt(g).pow((mod - 1) / i) == 1) {
                            ok = false;
                            break;
                        }
                    if (ok) return g;
                }
                return -1;
            }();
        }
        return primitive_root;
    }
    int val;
    MDCONST ModInt() : val(0) {}
    MDCONST ModInt &_setval(lint v) { return val = (v >= mod ? v - mod : v), *this; }
    MDCONST ModInt(lint v) { _setval(v % mod + mod); }
    MDCONST explicit operator bool() const { return val != 0; }
    MDCONST ModInt operator+(const ModInt &x) const { return ModInt()._setval((lint)val + x.val); }
    MDCONST ModInt operator-(const ModInt &x) const { return ModInt()._setval((lint)val - x.val + mod); }
    MDCONST ModInt operator*(const ModInt &x) const { return ModInt()._setval((lint)val * x.val % mod); }
    MDCONST ModInt operator/(const ModInt &x) const { return ModInt()._setval((lint)val * x.inv() % mod); }
    MDCONST ModInt operator-() const { return ModInt()._setval(mod - val); }
    MDCONST ModInt &operator+=(const ModInt &x) { return *this = *this + x; }
    MDCONST ModInt &operator-=(const ModInt &x) { return *this = *this - x; }
    MDCONST ModInt &operator*=(const ModInt &x) { return *this = *this * x; }
    MDCONST ModInt &operator/=(const ModInt &x) { return *this = *this / x; }
    friend MDCONST ModInt operator+(lint a, const ModInt &x) { return ModInt()._setval(a % mod + x.val); }
    friend MDCONST ModInt operator-(lint a, const ModInt &x) { return ModInt()._setval(a % mod - x.val + mod); }
    friend MDCONST ModInt operator*(lint a, const ModInt &x) { return ModInt()._setval(a % mod * x.val % mod); }
    friend MDCONST ModInt operator/(lint a, const ModInt &x) { return ModInt()._setval(a % mod * x.inv() % mod); }
    MDCONST bool operator==(const ModInt &x) const { return val == x.val; }
    MDCONST bool operator!=(const ModInt &x) const { return val != x.val; }
    MDCONST bool operator<(const ModInt &x) const { return val < x.val; } // To use std::map<ModInt, T>
    friend std::istream &operator>>(std::istream &is, ModInt &x) {
        lint t;
        return is >> t, x = ModInt(t), is;
    }
    MDCONST friend std::ostream &operator<<(std::ostream &os, const ModInt &x) { return os << x.val; }
    MDCONST ModInt pow(lint n) const {
        lint ans = 1, tmp = this->val;
        while (n) {
            if (n & 1) ans = ans * tmp % mod;
            tmp = tmp * tmp % mod, n /= 2;
        }
        return ans;
    }

    static std::vector<long long> facs, invs;
    MDCONST static void _precalculation(int N) {
        int l0 = facs.size();
        if (N <= l0) return;
        facs.resize(N), invs.resize(N);
        for (int i = l0; i < N; i++) facs[i] = facs[i - 1] * i % mod;
        long long facinv = ModInt(facs.back()).pow(mod - 2).val;
        for (int i = N - 1; i >= l0; i--) {
            invs[i] = facinv * facs[i - 1] % mod;
            facinv = facinv * i % mod;
        }
    }
    MDCONST lint inv() const {
        if (this->val < std::min(mod >> 1, 1 << 21)) {
            while (this->val >= int(facs.size())) _precalculation(facs.size() * 2);
            return invs[this->val];
        } else {
            return this->pow(mod - 2).val;
        }
    }
    MDCONST ModInt fac() const {
        while (this->val >= int(facs.size())) _precalculation(facs.size() * 2);
        return facs[this->val];
    }

    MDCONST ModInt doublefac() const {
        lint k = (this->val + 1) / 2;
        return (this->val & 1) ? ModInt(k * 2).fac() / (ModInt(2).pow(k) * ModInt(k).fac())
                               : ModInt(k).fac() * ModInt(2).pow(k);
    }
    MDCONST ModInt nCr(const ModInt &r) const {
        return (this->val < r.val) ? 0 : this->fac() / ((*this - r).fac() * r.fac());
    }

    ModInt sqrt() const {
        if (val == 0) return 0;
        if (mod == 2) return val;
        if (pow((mod - 1) / 2) != 1) return 0;
        ModInt b = 1;
        while (b.pow((mod - 1) / 2) == 1) b += 1;
        int e = 0, m = mod - 1;
        while (m % 2 == 0) m >>= 1, e++;
        ModInt x = pow((m - 1) / 2), y = (*this) * x * x;
        x *= (*this);
        ModInt z = b.pow(m);
        while (y != 1) {
            int j = 0;
            ModInt t = y;
            while (t != 1) j++, t *= t;
            z = z.pow(1LL << (e - j - 1));
            x *= z, z *= z, y *= z;
            e = j;
        }
        return ModInt(std::min(x.val, mod - x.val));
    }
};
template <int mod> std::vector<long long> ModInt<mod>::facs = {1};
template <int mod> std::vector<long long> ModInt<mod>::invs = {0};
using mint = ModInt<998244353>;

template <typename T> struct matrix {
    int H, W;
    std::vector<T> elem;
    typename std::vector<T>::iterator operator[](int i) { return elem.begin() + i * W; }
    inline T &at(int i, int j) { return elem[i * W + j]; }
    inline T get(int i, int j) const { return elem[i * W + j]; }
    operator std::vector<std::vector<T>>() const {
        std::vector<std::vector<T>> ret(H);
        for (int i = 0; i < H; i++)
            std::copy(elem.begin() + i * W, elem.begin() + (i + 1) * W, std::back_inserter(ret[i]));
        return ret;
    }

    matrix() = default;
    matrix(int H, int W) : H(H), W(W), elem(H * W) {}
    matrix(const std::vector<std::vector<T>> &d) : H(d.size()), W(d.size() ? d[0].size() : 0) {
        for (auto &raw : d) std::copy(raw.begin(), raw.end(), std::back_inserter(elem));
    }

    static matrix Identity(int N) {
        matrix ret(N, N);
        for (int i = 0; i < N; i++) ret.at(i, i) = 1;
        return ret;
    }

    matrix operator-() const {
        matrix ret(H, W);
        for (int i = 0; i < H * W; i++) ret.elem[i] = -elem[i];
        return ret;
    }
    matrix operator*(const T &v) const {
        matrix ret = *this;
        for (auto &x : ret.elem) x *= v;
        return ret;
    }
    matrix operator/(const T &v) const {
        matrix ret = *this;
        for (auto &x : ret.elem) x /= v;
        return ret;
    }
    matrix operator+(const matrix &r) const {
        matrix ret = *this;
        for (int i = 0; i < H * W; i++) ret.elem[i] += r.elem[i];
        return ret;
    }
    matrix operator-(const matrix &r) const {
        matrix ret = *this;
        for (int i = 0; i < H * W; i++) ret.elem[i] -= r.elem[i];
        return ret;
    }
    matrix operator*(const matrix &r) const {
        matrix ret(H, r.W);
        for (int i = 0; i < H; i++) {
            for (int k = 0; k < W; k++) {
                for (int j = 0; j < r.W; j++) { ret.at(i, j) += this->get(i, k) * r.get(k, j); }
            }
        }
        return ret;
    }
    matrix &operator*=(const T &v) { return *this = *this * v; }
    matrix &operator/=(const T &v) { return *this = *this / v; }
    matrix &operator+=(const matrix &r) { return *this = *this + r; }
    matrix &operator-=(const matrix &r) { return *this = *this - r; }
    matrix &operator*=(const matrix &r) { return *this = *this * r; }
    bool operator==(const matrix &r) const { return H == r.H and W == r.W and elem == r.elem; }
    bool operator!=(const matrix &r) const { return H != r.H or W != r.W or elem != r.elem; }
    bool operator<(const matrix &r) const { return elem < r.elem; }
    matrix pow(int n) const {
        matrix ret = Identity(H);
        if (n == 0) return ret;
        for (int i = 31 - __builtin_clz(n); i >= 0; i--) {
            ret *= ret;
            if ((n >> i) & 1) ret *= (*this);
        }
        return ret;
    }
    matrix transpose() const {
        matrix ret(W, H);
        for (int i = 0; i < H; i++)
            for (int j = 0; j < W; j++) ret.at(j, i) = this->get(i, j);
        return ret;
    }
    // Gauss-Jordan elimination
    // - Require inverse for every non-zero element
    // - Complexity: O(H^2 W)
    matrix gauss_jordan() const {
        int c = 0;
        matrix mtr(*this);
        std::vector<int> ws;
        ws.reserve(W);
        for (int h = 0; h < H; h++) {
            if (c == W) break;
            int piv = -1;
            for (int j = h; j < H; j++)
                if (mtr.get(j, c)) {
                    piv = j;
                    break;
                }
            if (piv == -1) {
                c++;
                h--;
                continue;
            }
            if (h != piv) {
                for (int w = 0; w < W; w++) {
                    std::swap(mtr[piv][w], mtr[h][w]);
                    mtr.at(piv, w) *= -1; // To preserve sign of determinant
                }
            }
            ws.clear();
            for (int w = c; w < W; w++) {
                if (mtr.at(h, w) != 0) ws.emplace_back(w);
            }
            const T hcinv = mtr.at(h, c).inv();
            for (int hh = 0; hh < H; hh++)
                if (hh != h) {
                    const T coeff = mtr.at(hh, c) * hcinv;
                    for (auto w : ws) mtr.at(hh, w) -= mtr.at(h, w) * coeff;
                }
            c++;
        }
        return mtr;
    }
    friend std::vector<T> operator*(const matrix &m, const std::vector<T> &v) {
        assert(m.W == int(v.size()));
        std::vector<T> ret(m.H);
        for (int i = 0; i < m.H; i++) {
            for (int j = 0; j < m.W; j++) { ret[i] += m.get(i, j) * v[j]; }
        }
        return ret;
    }
    friend std::vector<T> operator*(const std::vector<T> &v, const matrix &m) {
        assert(int(v.size()) == m.H);
        std::vector<T> ret(m.W);
        for (int i = 0; i < m.H; i++) {
            for (int j = 0; j < m.W; j++) { ret[j] += v[i] * m.get(i, j); }
        }
        return ret;
    }
    friend std::ostream &operator<<(std::ostream &os, const matrix &x) {
        os << "[(" << x.H << " * " << x.W << " matrix)";
        os << "\n[column sums: ";
        for (int j = 0; j < x.W; j++) {
            T s = 0;
            for (int i = 0; i < x.H; i++) s += x.get(i, j);
            os << s << ",";
        }
        os << "]";
        for (int i = 0; i < x.H; i++) {
            os << "\n[";
            for (int j = 0; j < x.W; j++) os << x.get(i, j) << ",";
            os << "]";
        }
        os << "]\n";
        return os;
    }
};

int main() {
    int N, M;
    cin >> N >> M;
    vector<string> S(N);
    cin >> S;
    sort(S.begin(), S.end());

    vector<vector<string>> words(11);
    for (auto s : S) words[s.length()].push_back(s);
    REP(i, 6) REP(j, 6) {
        for (auto s : words[i]) for (auto t : words[j]) {
            words[s.length() + t.length()].push_back(s + t);
        }
    }

    set<string> se;
    se.insert("");
    for (auto &v : words) {
        v = sort_unique(v);
        for (auto s : v) {
            FOR(d, 1, min<int>(4, s.length()) + 1) {
                se.insert(s.substr(0, d));
            }
            REP(i, s.length()) {
                FOR(d, 4, min<int>(4, s.length() - i) + 1) {
                    se.insert(s.substr(i, d));
                }
            }
        }
    }
    vector<string> dict(se.begin(), se.end());

    vector<string> dict_use;
    for (auto s : dict) {
        auto itr = lower_bound(ALL(S), s);
        if (itr != S.end() and itr->substr(0, s.length()) == s) dict_use.push_back(s);
    }
    dict = dict_use;

    dbg(dict);

    vector<int> head;
    using pss = pair<short, short>;
    vector<vector<pss>> ab;
    int D = 0;
    for (auto s : dict) {
        head.push_back(D);
        int l = s.length();
        ab.push_back({});
        REP(a, l + 1) FOR(b, a, l + 1) ab.back().emplace_back(a, b);
        D += ab.back().size();
    }
    matrix<mint> mat(D, D);
    dbg(D);

    REP(h, head.size()) {
        string u = dict.at(h);
        REP(c, 26) {
            string sss = u + char('a' + c);
            string snxt = sss;
            if (sss.length() == 5) snxt = sss.substr(1);
            int nxh = lower_bound(dict.begin(), dict.end(), snxt) - dict.begin();

            if (nxh < int(dict.size()) and dict[nxh] == snxt) {
                REP(i, ab[h].size()) {
                    const auto [a, b] = ab[h][i];

                    auto nxa = a, nxb = b;
                    if (sss.length() == 5) nxa--, nxb--;
                    if (nxa >= 0 and nxb >= 0) {
                        auto j = lower_bound(ALL(ab[nxh]), (nxa < nxb ? make_pair(nxa, nxb) : make_pair(nxb, nxa))) - ab[nxh].begin();
                        mat[head[nxh] + j][head[h] + i] += 1;
                    }
                    bool b1 = binary_search(ALL(S), sss.substr(a));
                    bool b2 = binary_search(ALL(S), sss.substr(b));
                    if (b1 and nxb >= 0) {
                        auto j = lower_bound(ALL(ab[nxh]), make_pair(nxb, short(snxt.length()))) - ab[nxh].begin();
                        mat[head[nxh] + j][head[h] + i] += 1;
                    }
                    if (b2 and nxa >= 0) {
                        auto j = lower_bound(ALL(ab[nxh]), make_pair(nxa, short(snxt.length()))) - ab[nxh].begin();
                        mat[head[nxh] + j][head[h] + i] += 1;
                    }
                    if (b1 and b2) {
                        mat[head[nxh] + ab[nxh].size() - 1][head[h] + i] += 1;
                    }
                }
            }
        }
    }
    vector<matrix<mint>> mats;
    mats.push_back(mat);
    while (mats.size() < 30) {
        auto m = mats.back();
        mats.push_back(m * m);
    }

    vector<mint> v(D);
    v[0] = 1;
    while (M) {
        if (M & 1) v = mat * v;
        mat = mat * mat;
        M /= 2;
    }

    mint ret = 0;
    REP(h, dict.size()) {
        int i = head[h] + ab[h].size() - 1;
        ret += v[i];
    }
    cout << ret << '\n';
}

#include <bits/stdc++.h>

#define F first
#define S second

using namespace std;
using ll = long long;
using pi = pair<int, int>;
using vi = vector<int>;
using vpi = vector<pi>;

template<class T> bool ckmin(T& a, T b) { return b < a ? a = b, true : false; }
template<class T> bool ckmax(T& a, T b) { return a < b ? a = b, true : false; }

const int MOD = 998244353;

struct Matrix {
    int n;
    vector<vector<int>> w;

    Matrix(const int n) : n(n), w(n, vector<int>(n)) { }

    Matrix operator * (const Matrix& m) const {
        Matrix res(n);

        for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j) {
            if (!w[i][j]) continue;
            for (int t = 0; t < n; ++t) {
                res.w[i][t] = (res.w[i][t] + (ll) w[i][j] * m.w[j][t]) % MOD;
            }
        }

        return res;
    }
};

void dfs_forw(int v, const int r, const vector<vector<int>>& w, vector<char>& used) {
    if (used[v]) return;
    used[v] = true;

    for (int i = 0; i < r; ++i) {
        if (w[v][i]) dfs_forw(i, r, w, used);
    }
}

void dfs_back(int v, const int r, const vector<vector<int>>& w, vector<char>& used) {
    if (used[v]) return;
    used[v] = true;

    for (int i = 0; i < r; ++i) {
        if (w[i][v]) dfs_forw(i, r, w, used);
    }
}

void solve() {
    int n, m; cin >> n >> m;

    map<string, int> id;
    id[""] = 0;
    int vc = 1;

    vector<string> v(n), phi { "" };
    for (string& s : v) {
        cin >> s;
        for (int i = 1; i <= size(s); ++i) {
            auto t = s.substr(0, i);
            if (!id.count(t)) {
                id[t] = vc++;
                phi.push_back(t);
            }
        }
    }

    const int k = size(id);
    const int r = k * k;
    vector w(r, vector<int>(r));

    for (int ia = 0; ia < k; ++ia)
    for (int ib = 0; ib < k; ++ib) {
        for (char ch = 'a'; ch <= 'z'; ch++) {
            auto ta = phi[ia] + ch; const int sa = id.count(ta) ? id[ta] : -1;
            auto tb = phi[ib] + ch; const int sb = id.count(tb) ? id[tb] : -1;

            for (int ja = 0; ja < n; ++ja) {
                if (ta != v[ja]) continue;
                for (int jb = 0; jb < n; ++jb) {
                    if (tb != v[jb]) continue;
                    w[ia*k+ib][0]++;
                }

                if (sb != -1) w[ia*k+ib][sb]++;
            }

            for (int jb = 0; jb < n; ++jb) {
                if (sa != -1 && tb == v[jb]) w[ia*k+ib][sa*k]++;
            }

            if (sa != -1 && sb != -1) w[ia*k+ib][sa*k+sb]++;
        }
    }

    vector<char> u1(r), u2(r);
    int us = 0;

    dfs_forw(0, r, w, u1);
    dfs_back(0, r, w, u2);

    vector<int> tid;

    for (int i = 0; i < r; ++i) {
        if (u1[i] && u2[i]) {
            tid.push_back(i);
        }
    }

    const int p = size(tid);

    Matrix ans(p), mul(p);

    for (int i = 0; i < p; ++i)
    for (int j = 0; j < p; ++j) {
        mul.w[i][j] = w[tid[i]][tid[j]];
    }

    for (int i = 0; i < p; ++i) ans.w[i][i] = 1;

    for (; m != 0; m >>= 1) {
        if (m & 1) ans = ans * mul;
        mul = mul * mul;
    }

    cout << ans.w[0][0] << '\n';
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    int t = 1;
    // cin >> t;
    while (t--) solve();
}

// dp[0] = 1
// dp[1] = 1
// dp[2] = 2
// dp[3] = 3
// dp[4] = 5

#include<bits/stdc++.h>
using namespace std;

const long long mod = 998244353;

vector<vector<long long>> matmul(vector<vector<long long>> A,vector<vector<long long>> B)
{
    int N = A.size();
    vector<vector<long long>> ans(N,vector<long long>(N,0));
    for(int i = 0;i < N;++i)
    {
        for(int j = 0;j < N;++j){
            for(int k = 0;k < N;++k){
                ans[i][k] += A[i][j]*B[j][k];
                ans[i][k]%=mod;
            }
        }
    }
    return ans;
}

vector<vector<long long>> matexp(vector<vector<long long>> A,long long b){
    int N = A.size();
    vector<vector<long long>> ans(N,vector<long long>(N,0));
    for(int i = 0;i < N;++i){
        ans[i][i] = 1;
    }
    while(b > 0){
        if(b%2 == 1){
            ans = matmul(ans,A);
        }
        A = matmul(A,A);
        b/=2;
    }
    return ans;
}

int main()
{
    int n,m;
    cin >> n >> m;
    vector<string> S(n);
    for(int i = 0;i < n;++i){
        cin >> S[i];
    }
    vector<pair<string,string>> state;
    for(int i = 0;i < n;++i){
        int sz = S[i].size();
        for(int j = 0;j <= sz;++j){
            for(int k = 0;k <= sz-j;k++){
                string s = S[i].substr(j,k);
                string t = S[i].substr(j);
                state.push_back(make_pair(s,t));
            }
        }
    }
    sort(state.begin(),state.end());
    state.erase(unique(state.begin(),state.end()),state.end());
    int cnt = state.size();
    map<pair<string,string>,int> mp;
    for(int i = 0;i < cnt;++i){
        mp[state[i]] = i;
        //cout << "QAQ " << state[i].second << " " << i << endl;
    }
    vector<vector<long long>> A(cnt,vector<long long>(cnt,0));
    for(int i = 0;i < cnt;++i){
        string s = state[i].first;
        string t = state[i].second;
        //cout << "QAQ " << s << " " << t << endl;
        if(!s.empty()){
            s.erase(s.begin());
            t.erase(t.begin());
            int id = mp[make_pair(s,t)];
            A[i][id]++;
        }
        else if(!t.empty()){
            for(int j = 0;j < n;++j){
                int mn = min(S[j].size(),t.size());
                if(S[j].substr(0,mn) == t.substr(0,mn)){
                    string s2 = S[j].substr(1);
                    string t2 = t.substr(1);
                    if(s2.size() > t2.size()){
                        swap(s2,t2);
                    }
                    int id = mp[make_pair(s2,t2)];
                    A[i][id]++;
                }
            }
        } else{
            for(int j = 0;j < n;++j){
                for(int k = 0;k < n;++k){
                    int mn = min(S[j].size(),S[k].size());
                    if(S[j].substr(0,mn) == S[k].substr(0,mn)){
                        string s2 = S[j].substr(1);
                        string t2 = S[k].substr(1);
                        if(s2.size() > t2.size()){
                            swap(s2,t2);
                        }
                        int id = mp[make_pair(s2,t2)];
                        //if(i == 0) cout << "QAQ " << s2 << " " << id << endl;
                        A[i][id]++;
                    }
                }
            }
        }
    }
    cout << "QAQ " << A[0][0] << endl;
    A = matexp(A,m);
    cout << A[0][0] << endl;
}

#include <bits/stdc++.h>

using namespace std;

#ifdef Adrian
#include "debug.h"
#else
#define debug(...) 9999
#endif

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef complex<ll> point;
#define F first
#define S second
#define ii pair<int, int>

ll mod = 998244353;
vector<vector<ll>> mul(vector<vector<ll>> a, vector<vector<ll>> b)
{
    int n = a.size();
    vector<vector<ll>> c(n, vector<ll>(n));
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
            for(int k=0; k<n; k++)
                c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % mod;
    return c;
}
vector<vector<ll>> pot(vector<vector<ll>> a, int b)
{
    int n = a.size();
    vector<vector<ll>> c(n, vector<ll>(n));
    for(int i=0; i<n; i++) c[i][i] = 1;
    for(; b>0; b>>=1)
    {
        if(b & 1) c = mul(c, a);
        a = mul(a, a);
    }
    return c;
}

int main()
{
#ifdef Adrian
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
#else
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif

    int n, m;
    cin>>n>>m;

    vector<string> v(n);
    for(auto &i:v) cin>>i;
    sort(v.begin(), v.end(), [](string &x, string &y)
    { return x.size() > y.size(); });

    vector<vector<int>> f(n);
    vector<bool> fin = {false};
    vector<vector<int>> ch;
    ch.push_back(vector<int>(26, -1));

    for(int i=0; i<n; i++)
    {
        int r = 0;
        for(auto &j:v[i])
        {
            int c = j - 'a';
            if(ch[r][c] == -1)
            {
                ch.push_back(vector<int>(26, -1));
                ch[r][c] = fin.size();
                fin.push_back(false);
            }

            r = ch[r][c];
            f[i].push_back(r);
        }
        fin[r] = true;
    }

    int p = 0;
    int sz = ch.size();
    vector<vector<int>> valid(sz,
            vector<int>(sz, -1));
    valid[0][0] = p++;
    for(int i=0; i<n; i++)
        for(int j=i; j<n; j++)
            for(int ti=0; ti<v[i].size(); ti++)
                for(int tj=0; tj<v[j].size(); tj++)
                {
                    int a = f[i][ti], b = f[j][tj];
                    if(valid[a][b] != -1) continue;
                    bool ok = true;
                    for(int k=0; k<=min(ti, tj); k++)
                        ok |= (v[i][ti-k] == v[j][tj-k]);
                    if(ok) valid[a][b] = p++;
                }
    for(int i=1; i<sz; i++)
    {
        valid[0][i] = p++;
        valid[i][0] = p++;
    }

    vector<vector<ll>> mat(p,
            vector<ll>(p));
    for(int i=0; i<sz; i++)
        for(int j=0; j<sz; j++)
        {
            if(valid[i][j] == -1) continue;
            int x = valid[i][j];
            for(int k=0; k<26; k++)
            {
                int a = ch[i][k], b = ch[j][k];
                if(a != -1 && b != -1)
                {
                    if(valid[a][b] != -1) ++mat[x][valid[a][b]];
                    if(fin[a]) ++mat[x][valid[0][b]];
                    if(fin[b]) ++mat[x][valid[a][0]];
                    if(fin[a] && fin[b]) ++mat[x][0];
                }
            }
        }

    auto ans = pot(mat, m);
    cout<<ans[0][0]<<'\n';

    return 0;
}

/*
3 5
ababa
ab
a

2 4
ab
cd

5 100
a
aa
aaa
aaaa
aaaaa

8 3
ba
bbb
bb
aba
aab
baa
b
a

 */

#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) 114514
#endif

#define fi first
#define se second
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using ai3 = array<int, 3>;
using al3 = array<ll, 3>;
mt19937 mrnd(random_device{}());

int rnd(int mod) {
    return mrnd() % mod;
}

// region 自动取模类
template<int MOD, int RT>
struct mint {
    static constexpr mint rt() { return RT; } // primitive root for FFT
    int v;

    explicit operator int() const { return v; } // explicit -> don't silently convert to int
    mint() : v(0) {}

    mint(ll _v) {
        v = int((-MOD < _v && _v < MOD) ? _v : _v % MOD);
        if (v < 0) v += MOD;
    }

    bool operator==(const mint &o) const {
        return v == o.v;
    }

    friend bool operator!=(const mint &a, const mint &b) {
        return !(a == b);
    }

    friend bool operator<(const mint &a, const mint &b) {
        return a.v < b.v;
    }

    mint &operator+=(const mint &o) {
        if ((v += o.v) >= MOD) v -= MOD;
        return *this;
    }

    mint &operator-=(const mint &o) {
        if ((v -= o.v) < 0) v += MOD;
        return *this;
    }

    mint &operator*=(const mint &o) {
        v = int((ll) v * o.v % MOD);
        return *this;
    }

    mint &operator/=(const mint &o) { return (*this) *= inv(o); }

    friend mint qpow(mint a, ll p) {
        mint ans = 1;
        assert(p >= 0);
        for (; p; p /= 2, a *= a) if (p & 1) ans *= a;
        return ans;
    }

    friend mint inv(const mint &a) {
        assert(a.v != 0);
        return qpow(a, MOD - 2);
    }

    mint operator-() const { return mint(-v); }

    mint &operator++() { return *this += 1; }

    mint &operator--() { return *this -= 1; }

    mint operator++(int) {
        mint tmp = *this;
        *this += 1;
        return tmp;
    }

    mint operator--(int) {
        mint tmp = *this;
        *this -= 1;
        return tmp;
    }

    friend mint operator+(mint a, const mint &b) { return a += b; }

    friend mint operator-(mint a, const mint &b) { return a -= b; }

    friend mint operator*(mint a, const mint &b) { return a *= b; }

    friend mint operator/(mint a, const mint &b) { return a /= b; }

    friend istream &operator>>(istream &is, mint &a) {
        ll tv;
        is >> tv;
        a = mint(tv);
        return is;
    }

    friend ostream &operator<<(ostream &os, const mint &a) {
        return os << a.v;
    }
};
// endregion

// region 矩阵(Z)
template<int SZ, class Z>
struct Mat {
    int r, c;
    Z a[SZ + 1][SZ + 1];

    Mat() {}

    void init(int _r, int _c) {
        r = _r, c = _c;
    }

    inline void operator=(Z x) {
        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= c; j++) {
                a[i][j] = i == j ? x : 0;
            }
        }
    }

    // _a: 0 base, a: 1 base
    inline void operator=(const vector<vector<Z>> &_a) {
        assert(r == _a.size() && c == _a[0].size());

        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= c; j++) {
                a[i][j] = _a[i - 1][j - 1];
            }
        }
    }

    inline Mat operator+(const Mat &T) const {
        assert(r == T.r && c == T.c);

        Mat res;
        res.init(r, c);
        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= c; j++) {
                res.a[i][j] = a[i][j] + T.a[i][j];
            }
        }
        return res;
    }

    inline Mat operator-(const Mat &T) const {
        assert(r == T.r && c == T.c);

        Mat res;
        res.init(r, c);
        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= c; j++) {
                res.a[i][j] = a[i][j] - T.a[i][j];
            }
        }
        return res;
    }

    inline Mat operator*(const Mat &T) const {
        assert(c == T.r);

        Mat res;
        res.init(r, T.c);
        for (int i = 1; i <= res.r; i++) {
            for (int j = 1; j <= res.c; j++) {
                res.a[i][j] = 0;
                for (int k = 1; k <= c; k++) {
                    res.a[i][j] = res.a[i][j] + a[i][k] * T.a[k][j];
                }
            }
        }
        return res;
    }

    inline Mat operator*(Z x) const {
        Mat res;
        res.init(r, c);
        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= c; j++) {
                res.a[i][j] = a[i][j] * x;
            }
        }
        return res;
    }

    inline Mat operator^(ll x) const {
        assert(r == c);

        Mat res, bas;
        res.init(r, c), bas.init(r, c);
        res = 1, bas = *this;

        while (x) {
            if (x & 1) res = res * bas;
            bas = bas * bas;
            x >>= 1;
        }
        return res;
    }

    inline bool operator==(const Mat &T) const {
        if (r != T.r || c != T.c) return false;
        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= c; j++) {
                if (a[i][j] != T.a[i][j]) return false;
            }
        }
        return true;
    }

    inline void print() const {
        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= c; j++) {
                cout << a[i][j] << " \n"[j == c];
            }
        }
    }
};
// endregion

// region trie
// 字符总长 SZ, 字符集大小 C
// 默认小写字母
template<int SZ, int C = 26>
struct Trie {
    int rt;
    int ne[SZ + 10][C], mem;
    int cnt[SZ + 10];

    Trie() {}

    void init() {
        mem = 0;
        rt = new_node();
        fill(&ne[0][0], &ne[0][C], 0);
        cnt[0] = 0;
    }

    int new_node() {
        int id = ++mem;
        fill(&ne[id][0], &ne[id][C], 0);
        cnt[id] = 0;
        return id;
    }

    void ins(const string &s) {
        int u = rt;
        for (char ch : s) {
            int &v = ne[u][ch - 'a'];
            if (!v) v = new_node();
            u = v;
        }

        cnt[u]++;
    }

    int qr(const string &s) {
        int u = rt, res = 0;
        for (char ch : s) {
            int v = ne[u][ch - 'a'];
            if (!v) break;

            u = v;
            res += cnt[u];
        }

        return res;
    }
};
// endregion

const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
const int MOD = 998244353;
const int N = 11;
const int B = 44;

using Z = mint<MOD, 5>;

int n, m;
string a[N];
Trie<B> tr;
int ids[B][B], tt;
int vis[B][B];
Mat<B * B, Z> coef, A;

inline int get(int u, int v) {
    if (u > v) swap(u, v);
    if (!ids[u][v]) ids[u][v] = ++tt;
    return ids[u][v];
}

void solve() {
    tr.init();
    for (int i = 1; i <= n; i++) tr.ins(a[i]);

    coef.init(1600, 1600);

    queue<pii> que;
    vis[1][1] = 1;
    que.push({1, 1});
    while (!que.empty()) {
        auto [x, y] = que.front(); que.pop();

        for (char ch = 'a'; ch <= 'z'; ch++) {
            int u = get(x, y);

            int nx = tr.ne[x][ch - 'a'], ny = tr.ne[y][ch - 'a'];
            if (nx == 0 || ny == 0) continue;

            coef.a[u][get(nx, ny)]++;
            que.push({nx, ny});
            if (tr.cnt[nx]) {
                coef.a[u][get(1, ny)]++;
                if (!vis[1][ny]) {
                    vis[1][ny] = 1;
                    que.push({1, ny});
                }
            }
            if (tr.cnt[ny]) {
                coef.a[u][get(nx, 1)]++;
                if (!vis[nx][1]) {
                    vis[nx][1] = 1;
                    que.push({nx, 1});
                }
            }
            if (tr.cnt[nx] && tr.cnt[ny]) {
                coef.a[u][get(1, 1)]++;
                if (!vis[1][1]) {
                    vis[1][1] = 1;
                    que.push({1, 1});
                }
            }
        }
    }
    coef.r = coef.c = tt;

    A.init(tt, 1);
    A.a[1][1] = 1;

    A = (coef ^ m) * A;

    cout << A.a[1][1] << "\n";
}

void prework() {
}

int main() {
#ifdef LOCAL
    freopen("../in.txt", "r", stdin);
    freopen("../out.txt", "w", stdout);
    freopen("../err.txt", "w", stderr);
#endif

    prework();
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _ = 1;
//    cin >> _;
    while (_--) {
        cin >> n >> m;
        for (int i = 1; i <= n; i++) cin >> a[i];
        solve();
    }

    return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353,N=165;
int ch[N][N],ed[N],id[N][N],tot;
struct mat{ll a[N][N];}M;
mat operator*(const mat &a,const mat &b){
    mat r;memset(r.a,0,sizeof r.a);
    for(int i=1;i<=tot;i++)for(int k=1;k<=tot;k++)for(int j=1;j<=tot;j++)(r.a[i][j]+=a.a[i][k]*b.a[k][j])%=mod;
    return r;
}
int dfs(int x,int y){
    auto&u=id[x][y];if(u)return u;
    u=id[y][x]=++tot;
    for(int i=0;i<26;i++){
        int nx=ch[x][i],ny=ch[y][i];
        if(nx&&ny){
            M.a[u][dfs(nx,ny)]++;
            if(ed[nx])M.a[u][dfs(1,ny)]++;
            if(ed[ny])M.a[u][dfs(1,nx)]++;
            if(ed[ny]&&ed[nx])M.a[u][dfs(1,1)]++;
        }
    }
    return u;
}
int main(){
    int n,m,p,sz=1;cin>>n>>m,--m;string s;
    while(n--){
        cin>>s,p=1;
        for(auto c:s){
            auto&nx=ch[p][c-'a'];
            if(!nx)nx=++sz;p=nx;
        }ed[p]=1;
    }
    dfs(1,1);mat r=M;
    for (int i=1;i<=tot;++i)
	 for(int j=1;j<=tot;++j)
	  cout<<r.a[i][j];
    for(;m;m>>=1,M=M*M)if(m&1)r=r*M;
    cout<<r.a[1][1];
}

// This code wrote by chtholly_micromaker(Myukiyomekya)
#include <bits/stdc++.h>
#define reg
#define int long long
#define ALL(x) (x).begin(),(x).end()
#define mem(x,y) memset(x,y,sizeof x)
#define sz(x) (int)(x).size()
#define ln putchar('\n')
#define lsp putchar(32)
#define pb push_back
#define MP std::make_pair
#define MT std::make_tuple
#ifdef _LOCAL_
#define dbg(x) std::cerr<<__func__<<"\tLine:"<<__LINE__<<' '<<#x<<": "<<x<<"\n"
#define dprintf(x...) std::fprintf(stderr,x)
#else
#define dbg(x) 42
#define dprintf(x...) 42
#endif
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,b,a) for(int i=(b);i>=(a);--i)
typedef std::pair<int,int> pii;
typedef std::vector<int> poly;
template <class t> inline void read(t &s){s=0;
signed f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c))s=(s<<3)+(s<<1)+(c^48),c=getchar();;s*=f;}
template<class t,class ...A> inline void read(t &x,A &...a){read(x);read(a...);}
template <class t> inline void write(t x){if(x<0)putchar('-'),x=-x;
static int buf[50],top=0;while(x)buf[++top]=x%10,x/=10;if(!top)buf[++top]=0;
while(top)putchar(buf[top--]^'0');}
inline void setIn(std::string s){freopen(s.c_str(),"r",stdin);return;}
inline void setOut(std::string s){freopen(s.c_str(),"w",stdout);return;}
inline void setIO(std::string s=""){setIn(s+".in");setOut(s+".out");return;}
template <class t>inline bool ckmin(t&x,t y){if(x>y){x=y;return 1;}return 0;}
template <class t>inline bool ckmax(t&x,t y){if(x<y){x=y;return 1;}return 0;}
inline int lowbit(int x){return x&(-x);}
const int p=998244353;
struct Mat
{
	int a[121][121];
	Mat(){std::mem(a,0);}
	inline Mat operator * (const Mat &nt) const
	{
		Mat ret;
		rep(i,1,120)rep(k,1,120)rep(j,1,120)
			(ret.a[i][j]+=a[i][k]*nt.a[k][j])%=p;
		return ret;
	}
}base,I;
char s[145];
int ch[1050][26],ed[1050],ndn;
inline void insert(char *s)
{
	int p=0;
	for(;*s;++s)
	{
		int d=*s-'a';
		if(!ch[p][d])ch[p][d]=++ndn;
		p=ch[p][d];
	}
	ed[p]=1;
}
#define fi first
#define se second
std::map<pii ,int> idx;int idxc;
std::queue<pii > Q;
inline int push(pii x)
{
	if(x.fi>x.se)std::swap(x.fi,x.se);
	if(idx.count(x))return idx[x];
	idx[x]=++idxc,Q.push(x);
	return idxc;
}
signed main(void)
{
	rep(i,1,120)I.a[i][i]=1;
	int n,m;read(n,m);
	rep(i,1,n)std::scanf("%s",s),insert(s);
	push(MP(0,0));
	while(!Q.empty())
	{
		auto u=Q.front();Q.pop();
		rep(i,0,25)
		{
			pii nxt=MP(ch[u.fi][i],ch[u.se][i]);
			if(!nxt.fi||!nxt.se)continue;
			++base.a[push(u)][push(nxt)];
			if(ed[nxt.fi])++base.a[push(u)][push(MP(0,nxt.se))];
			if(ed[nxt.se])++base.a[push(u)][push(MP(nxt.fi,0))];
			if(ed[nxt.fi]&&ed[nxt.se])++base.a[push(u)][push(MP(0,0))];
		}
	}
	Mat ret=I;
	for(;m;m>>=1,base=base*base)if(m&1)ret=ret*base;
	write(ret.a[1][1]),ln;
	return 0;
}

/*
 * Check List:
 * 1. Input / Output File (OI)
 * 2. long long
 * 3. Special Test such as n=1
 * 4. Array Size
 * 5. Memory Limit (OI) int is 4 and longlong is 8
 * 6. Mod (a*b%p*c%p not a*b*c%p  ,  (a-b+p)%p not a-b )
 * 7. Name ( int k; for(int k...))
 * 8. more tests , (T=2 .. more)
 * 9. blank \n after a case
*/

#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define uid uniform_int_distribution
#define uint unsigned int
#define ld long double
#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define ar array
#define f first
#define s second
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rint(l, r) uid<int>(l, r)(rng)
template<class T> using pq = priority_queue<T>;
template<class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}
template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.f); cerr << ','; __print(x.s); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif
template <int MOD_> struct modnum {
    static constexpr int MOD = MOD_;

    int v;

    modnum() : v(0) {}
    modnum(ll v_) : v(int(v_ % MOD)) { if (v < 0) v += MOD; }
    explicit operator int() const { return v; }
    explicit operator bool() const { return v; }

    friend ostream& operator << (ostream& out, const modnum& n) { return out << int(n); }
    friend istream& operator >> (istream& in, modnum& n) { ll v_; in >> v_; n = modnum(v_); return in; }

    friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
    friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }
    friend bool operator ! (const modnum &a) { return a.v == 0; }

    modnum operator- () const {
        return neg();
    }
    modnum operator+ () const {
        return modnum(*this);
    }

    modnum& operator ++ () {
        v++;
        if (v == MOD) v = 0;
        return *this;
    }
    modnum& operator -- () {
        if (v == 0) v = MOD;
        v--;
        return *this;
    }
    modnum& operator += (const modnum& o) {
        v -= MOD-o.v;
        v = (v < 0) ? v + MOD : v;
        return *this;
    }
    modnum& operator -= (const modnum& o) {
        v -= o.v;
        v = (v < 0) ? v + MOD : v;
        return *this;
    }
    modnum& operator *= (const modnum& o) {
        v = int((ll) v * o.v % MOD);
        return *this;
    }

    friend modnum binpow(modnum a, ll p) {
        if (p == 0) return 1;
        modnum ret = 1;
        for (; p; p /= 2, a *= a) if (p&1) ret *= a;
        return ret;
    }

    modnum inv() const {
        return binpow(*this, MOD-2);
    }
    friend modnum inv(const modnum& m) { return m.inv(); }

    modnum& operator /= (const modnum& o) {
        return *this *= o.inv();
    }

    modnum neg() const {
        modnum res;
        res.v = v ? MOD-v : 0;
        return res;
    }
    friend modnum neg(const modnum& m) { return m.neg(); }

    friend modnum operator ++ (modnum& a, int) { modnum r = a; ++a; return r; }
    friend modnum operator -- (modnum& a, int) { modnum r = a; --a; return r; }
    friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
    friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
    friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }
    friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= b; }
};

const int mod = 998244353;
using mint = modnum<mod>;

void __print(mint x) {cerr << x;}

vector<mint> facs, invfacs;

mint choose(const mint &a, const mint &b) {
    int _a = (int)a, _b = (int)b;
    if (_b > _a || _a < 0 || _b < 0) return 0;
    return facs[_a] * invfacs[_b] * invfacs[_a-_b];
}

void finit(const int nx) {
    facs.resize(nx+1);
    invfacs.resize(nx+1);
    facs[0] = facs[1] = invfacs[0] = invfacs[1] = 1;
    for (int i = 2; i <= nx; i++) {
        facs[i] = facs[i-1] * i;
    }
    invfacs[nx] = inv(facs[nx]);
    for (int i = nx-1; i > 1; i--) {
        invfacs[i] = invfacs[i+1] * (i+1);
    }
}

int NX;
struct Matrix {
    vector<vector<mint>> t;
    Matrix() : t(vector<vector<mint>>(NX, vector<mint>(NX))) {}
    Matrix operator * (const Matrix &other) {
        Matrix res;
        for (int i = 0; i < NX; i++) {
            for (int j = 0; j < NX; j++) {
                for (int k = 0; k < NX; k++) {
                    res.t[i][k] += t[i][j] * other.t[j][k];
                }
            }
        }
        return res;
    }
    void operator *= (const Matrix &other) {
        *this = *this * other;
    }
    void operator ^= (ll k) {
        assert(k >= 0);
        Matrix res;
        for (int i = 0; i < NX; i++) res.t[i][i] = 1;
        while (k) {
            if (k&1) res *= *this;
            *this *= *this;
            k >>= 1;
        }
        *this = res;
    }
};

void test_case() {
    int a, b; cin >> a >> b;
    vector<string> t(a);
    for (auto &x : t) cin >> x;
    vector<string> each = {""};
    for (int i = 0; i < a; i++) {
        string cur;
        for (int j = 0; j < sz(t[i]); j++) {
            cur += t[i][j];
            each.push_back(cur);
        }
    }
    sort(all(each));
    each.erase(unique(all(each)), each.end());
    const int N = sz(each);
    map<string, int> mp;
    for (int i = 0; i < N; i++) {
        mp[each[i]] = i;
    }
    vector<bool> skip(N);
    for (int j = 0; j < N; j++) {
        skip[j] = find(all(t), each[j]) != t.end();
    }
    vector<vector<mint>> dp(N, vector<mint>(N));
    dp[0][0] = 1;
    vector<pii> ok;
    vector<int> states;
    auto turn = [&](int x, int y) {
        states.push_back(x*N+y);
        return x*N+y;
    };
    for (int i = 0; i < min(10, b); i++) {
        vector<vector<mint>> dp2(N, vector<mint>(N));
        for (int j = 0; j < N; j++) {
            for (int k = 0; k < N; k++) {
                if (dp[j][k]) {
                    for (char l = 'a'; l <= 'z'; l++) {
                        if (!mp.count(each[j] + l) || !mp.count(each[k] + l)) continue;
                        int pos1 = mp[each[j] + l];
                        int pos2 = mp[each[k] + l];
                        int _p = turn(j, k);
                        if (skip[pos1]) dp2[0][pos2] += dp[j][k], ok.push_back({_p, turn(0, pos2)});
                        if (skip[pos2]) dp2[pos1][0] += dp[j][k], ok.push_back({_p, turn(pos1, 0)});
                        if (skip[pos1]&&skip[pos2]) dp2[0][0] += dp[j][k], ok.push_back({_p, 0});
                        dp2[pos1][pos2] += dp[j][k];
                        ok.push_back({_p, turn(pos1, pos2)});
                    }
                }
            }
        }
        swap(dp, dp2);
    }
    sort(all(ok));
    ok.erase(unique(all(ok)), ok.end());
    sort(all(states));
    states.erase(unique(all(states)), states.end());
    NX = sz(states);
    Matrix first, expo;
    for (const auto &[x, y] : ok) {
        int _x = lower_bound(all(states), x) - states.begin();
        int _y = lower_bound(all(states), y) - states.begin();
        expo.t[_x][_y] = 1;
    }
    first.t[0][0] = 1;
    expo ^= b;
    first *= expo;
    cout << first.t[0][0] << '\n';
}
int main() {
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
//    cin >> t;
    while (t--) test_case();
}

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
constexpr LL mod = 998244353;
constexpr int maxn = 200;
struct Mat{
    LL A[maxn][maxn];
    Mat(){
        memset(A, 0, sizeof A);
    }
    Mat operator * (const Mat& mat)const{
        Mat res;
        for(int i = 0; i < maxn; i += 1)
            for(int j = 0; j < maxn; j += 1)
                for(int k = 0; k < maxn; k += 1)
                    res.A[i][j] = (res.A[i][j] + A[i][k] * mat.A[k][j]) % mod;
        return res;
    }
};
Mat power(Mat a, LL r){
    Mat res;
    for(int i = 0; i < maxn; i += 1) res.A[i][i] = 1;
    for(; r; r >>= 1, a = a * a)
        if(r & 1) res = res * a;
    return res;
}
int main(){
    cin.sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<string> vs(n);
    for(auto& s : vs) cin >> s;
    vector<int> shift(n + 1);
    for(int i = 1; i <= n; i += 1)
        shift[i] = shift[i - 1] + vs[i - 1].size() - 1;
    int f = shift.back(), k = (f + 1) * (f + 1);
    vector<vector<int>> G(k), H(k);
    auto tr = [&](int x, int y){
        if(x == f){
            for(int i = 0; i < n; i += 1)
                if(y == shift[i]) return vs[i][0];
            return '\0';
        }
        if(y == f){
            for(int i = 0; i < n; i += 1)
                if(x == shift[i + 1] - 1) return vs[i].back();
            return '\0';
        }
        for(int i = 0; i < n; i += 1)
            if(x + 1 == y and x >= shift[i] and y < shift[i + 1]) return vs[i][x - shift[i] + 1];
        return '\0';
    };
    for(int i = 0; i <= f; i += 1)
        for(int j = 0; j <= f; j += 1)
            for(int x = 0; x <= f; x += 1)
                for(int y = 0; y <= f; y += 1){
                    if(i == f and x == f and j == f and y == f){
                        for(int k = 0; k < n; k += 1)
                            if(vs[k].size() == 1) G[i * (f + 1) + j].push_back(x * (f + 1) + y);
                        continue;
                    }
                    if(i == f and x == f){
                        for(int k = 0; k < n; k += 1){
                            if(vs[k].size() == 1 and tr(j, y) == vs[k][0]) G[i * (f + 1) + j].push_back(x * (f + 1) + y);
                        }
                        continue;
                    }
                    if(j == f and y == f){
                        for(int k = 0; k < n; k += 1){
                            if(vs[k].size() == 1 and tr(i, x) == vs[k][0]) G[i * (f + 1) + j].push_back(x * (f + 1) + y);
                        }
                        continue;
                    }
                    int ti = tr(i, x), tj = tr(j, y);
                    if(ti and tj and ti == tj){
                        G[i * (f + 1) + j].push_back(x * (f + 1) + y);
                    }
                }
    for(int i = 0; i < k; i += 1)
        for(int j : G[i]) H[j].push_back(i);
    vector<int> vG(k), vH(k);
    function<void(vector<vector<int>>&, vector<int>&, int)> DFS = [&](vector<vector<int>>& G, vector<int>& vis, int u){
        vis[u] = 1;
        for(int v : G[u]) if(not vis[v]) DFS(G, vis, v);
    };
    DFS(G, vG, k - 1);
    DFS(H, vH, k - 1);
    map<int, int> mp;
    int id = 0;
    for(int i = 0; i < k; i += 1)
        if(vG[i] and vH[i]) mp[i] = id ++;
    //cout << id << "\n";
    assert(id <= maxn);
    Mat mat;
    for(int i = 0; i < k; i += 1) if(mp.count(i))
        for(int j : G[i]) if(mp.count(j)){
            mat.A[mp[j]][mp[i]] += 1;
        }
    Mat res = power(mat, m);
    cout << res.A[mp[k - 1]][mp[k - 1]] << '\n';
    return 0;
}

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int read()
{
	int ret=0;bool f=0;char c=getchar();
	while(c>'9'||c<'0')f|=(c=='-'),c=getchar();
	while(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+(c^48),c=getchar();
	return f?-ret:ret;
}
const int maxn=160;
const int mod=998244353;
int n,m;
map<pair<int,int>,int>id;
struct matrix
{
	int num[maxn][maxn];
	matrix(){memset(num,0,sizeof num);}
	matrix operator *(const matrix &x)
	{
		matrix ret;
		for(int i=0;i<id.size();i++)
			for(int j=0;j<id.size();j++)
				for(int k=0;k<id.size();k++)
					(ret.num[i][j]+=(ll)num[i][k]*x.num[k][j]%mod)%=mod;
		return ret;
	}
	friend matrix qpow(matrix a,int b)
	{
		matrix ret;for(int i=0;i<id.size();i++)ret.num[i][i]=1;
		for(;b;b>>=1,a=a*a)if(b&1)ret=ret*a;
		return ret;
	}
}tran,ans;
struct trie
{
	#define S(u,i) t[u].ch[i]
	struct node{int ch[26];bool ed;}t[maxn];int cnt;
	void insert(string &s)
	{
		int p=0;
		for(char &c:s)
		{
			if(!S(p,c-'a'))S(p,c-'a')=++cnt;
			p=S(p,c-'a');
		}
		t[p].ed=1;
	}
	void dfs(int u1,int u2)
	{
		if(u1>u2)swap(u1,u2);
		if(id.count({u1,u2}))return;
		if(u1&&u2){int tmp=id.size();id[{u1,u2}]=tmp;}
		for(int i=0;i<26;i++)
			if(S(u1,i)&&S(u2,i))dfs(S(u1,i),S(u2,i));
	}
	void getid(){for(int i=0;i<=cnt;i++)dfs(0,i);}
	void getmat()
	{
		for(auto &i:id)
		{
			int x=i.first.first,y=i.first.second;
			for(int j=0;j<26;j++)
				if(S(x,j)&&S(y,j))
				{
					int tox=S(x,j),toy=S(y,j);
					if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
				}
			if(t[x].ed)
				for(int j=0;j<26;j++)
					if(S(0,j)&&S(y,j))
					{
						int tox=S(0,j),toy=S(y,j);
						if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
					}
			if(t[y].ed&&x!=y)
				for(int j=0;j<26;j++)
					if(S(x,j)&&S(0,j))
					{
						int tox=S(x,j),toy=S(0,j);
						if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
					}
			if(t[x].ed&&t[y].ed)
				for(int j=0;j<26;j++)
					if(S(0,j)&&S(0,j))
					{
						int tox=S(0,j),toy=S(0,j);
						if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
					}
			if(x!=y)
			{
				swap(x,y);
				for(int j=0;j<26;j++)
				if(S(x,j)&&S(y,j))
				{
					int tox=S(x,j),toy=S(y,j);
					if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
				}
				if(t[x].ed)
					for(int j=0;j<26;j++)
						if(S(0,j)&&S(y,j))
						{
							int tox=S(0,j),toy=S(y,j);
							if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
						}
				if(t[y].ed&&x!=y)
					for(int j=0;j<26;j++)
						if(S(x,j)&&S(0,j))
						{
							int tox=S(x,j),toy=S(0,j);
							if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
						}
				if(t[x].ed&&t[y].ed)
					for(int j=0;j<26;j++)
						if(S(0,j)&&S(0,j))
						{
							int tox=S(0,j),toy=S(0,j);
							if(tox<=toy)tran.num[i.second][id[{tox,toy}]]++;
						}
			}
		}
		for(int i=0;i<26;i++)
			if(S(0,i))ans.num[0][id[{S(0,i),S(0,i)}]]++;
	}
	#undef S
}tr;
int f[maxn];
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;i++){string s;cin>>s;tr.insert(s);}
	tr.getid();tr.getmat();
	ans=ans*qpow(tran,m-1);
	int sum=0;
	for(auto &i:id)
		if(tr.t[i.first.first].ed&&tr.t[i.first.second].ed)
			sum=((ll)sum+(1+(i.first.first!=i.first.second))*ans.num[0][i.second])%mod;
	printf("%d\n",sum);
	return 0;
}

#line 1 "codeforces-workspace/contest/1511/f/f.cpp"
// #undef _GLIBCXX_DEBUG
// #define NDEBUG
#include <bits/extc++.h>

#line 2 "Library/lib/alias"

/**
 * @file alias
 * @brief Alias
 */

#line 13 "Library/lib/alias"

#line 2 "Library/lib/bit"

#if __cplusplus > 201703L

#include <bit>

#else

#ifndef _GLIBCXX_BIT
#define _GLIBCXX_BIT 1

#include <limits>
#include <type_traits>

namespace std {

template <typename _Tp> constexpr _Tp __rotl(_Tp __x, int __s) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  const int __r = __s % _Nd;
  if (__r == 0)
    return __x;
  else if (__r > 0)
    return (__x << __r) | (__x >> ((_Nd - __r) % _Nd));
  else
    return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd));  // rotr(x, -r)
}

template <typename _Tp> constexpr _Tp __rotr(_Tp __x, int __s) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  const int __r = __s % _Nd;
  if (__r == 0)
    return __x;
  else if (__r > 0)
    return (__x >> __r) | (__x << ((_Nd - __r) % _Nd));
  else
    return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd));  // rotl(x, -r)
}

template <typename _Tp> constexpr int __countl_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) {
    constexpr int __diff = _Nd_u - _Nd;
    return __builtin_clz(__x) - __diff;
  } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) {
    constexpr int __diff = _Nd_ul - _Nd;
    return __builtin_clzl(__x) - __diff;
  } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) {
    constexpr int __diff = _Nd_ull - _Nd;
    return __builtin_clzll(__x) - __diff;
  } else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    unsigned long long __high = __x >> _Nd_ull;
    if (__high != 0) {
      constexpr int __diff = (2 * _Nd_ull) - _Nd;
      return __builtin_clzll(__high) - __diff;
    }
    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    return (_Nd - _Nd_ull) + __builtin_clzll(__low);
  }
}

template <typename _Tp> constexpr int __countl_one(_Tp __x) noexcept {
  if (__x == numeric_limits<_Tp>::max()) return numeric_limits<_Tp>::digits;
  return __countl_zero<_Tp>((_Tp)~__x);
}

template <typename _Tp> constexpr int __countr_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
    return __builtin_ctz(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
    return __builtin_ctzl(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
    return __builtin_ctzll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    if (__low != 0) return __builtin_ctzll(__low);
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_ctzll(__high) + _Nd_ull;
  }
}

template <typename _Tp> constexpr int __countr_one(_Tp __x) noexcept {
  if (__x == numeric_limits<_Tp>::max()) return numeric_limits<_Tp>::digits;
  return __countr_zero((_Tp)~__x);
}

template <typename _Tp> constexpr int __popcount(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return 0;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
    return __builtin_popcount(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
    return __builtin_popcountl(__x);
  else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
    return __builtin_popcountll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_popcountll(__low) + __builtin_popcountll(__high);
  }
}

template <typename _Tp> constexpr bool __has_single_bit(_Tp __x) noexcept {
  return __popcount(__x) == 1;
}

template <typename _Tp> constexpr _Tp __bit_ceil(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0 || __x == 1) return 1;
  auto __shift_exponent = _Nd - __countl_zero((_Tp)(__x - 1u));
#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
  if (!__builtin_is_constant_evaluated()) {
    __glibcxx_assert(__shift_exponent != numeric_limits<_Tp>::digits);
  }
#endif
  using __promoted_type = decltype(__x << 1);
  if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) {
    const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2;
    __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp;
  }
  return (_Tp)1u << __shift_exponent;
}

template <typename _Tp> constexpr _Tp __bit_floor(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0) return 0;
  return (_Tp)1u << (_Nd - __countl_zero((_Tp)(__x >> 1)));
}

template <typename _Tp> constexpr _Tp __bit_width(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  return _Nd - __countl_zero(__x);
}

}  // namespace std

#endif

#endif
#line 2 "Library/lib/limits"

#line 4 "Library/lib/limits"

namespace workspace {

template <class _Tp> struct numeric_limits : std::numeric_limits<_Tp> {};

#ifdef __SIZEOF_INT128__

template <> struct numeric_limits<__uint128_t> {
  constexpr static __uint128_t max() { return ~__uint128_t(0); }
  constexpr static __uint128_t min() { return 0; }
};

template <> struct numeric_limits<__int128_t> {
  constexpr static __int128_t max() {
    return numeric_limits<__uint128_t>::max() >> 1;
  }
  constexpr static __int128_t min() { return -max() - 1; }
};

#endif

}  // namespace workspace
#line 16 "Library/lib/alias"

namespace workspace {

constexpr char eol = '\n';

using namespace std;

using i32 = int_least32_t;
using u32 = uint_least32_t;
using i64 = int_least64_t;
using u64 = uint_least64_t;

#ifdef __SIZEOF_INT128__
using i128 = __int128_t;
using u128 = __uint128_t;
#else
#warning 128bit integer is not available.
#endif

namespace _alias_impl {

template <class> struct first_arg { using type = void; };

template <class _Tp, class = void> struct parse_comp : first_arg<_Tp> {};

template <class _Tp>
struct parse_comp<_Tp, std::__void_t<decltype(&_Tp::operator())>>
    : first_arg<decltype(&_Tp::operator())> {};

template <class _R, class _Tp, class... _Args>
struct first_arg<_R(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _R, class _Tp, class... _Args>
struct first_arg<_R (*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...) const> {
  using type = _Tp;
};

}  // namespace _alias_impl

template <class _Tp = void, class _Compare = std::less<_Tp>>
decltype(auto) make_priority_queue(_Compare __x = _Compare()) noexcept {
  using type = std::conditional_t<
      std::is_void<_Tp>::value,
      std::decay_t<typename _alias_impl::parse_comp<_Compare>::type>, _Tp>;

  return std::priority_queue<type, std::vector<type>, _Compare>(__x);
}

template <class _Tp = void, class _Compare = std::less<_Tp>>
decltype(auto) make_set(_Compare __x = _Compare()) noexcept {
  using type = std::conditional_t<
      std::is_void<_Tp>::value,
      std::decay_t<typename _alias_impl::parse_comp<_Compare>::type>, _Tp>;

  return std::set<type, _Compare>(__x);
}

template <class _Key, class _Mapped, class _Compare = std::less<_Key>>
decltype(auto) make_map(_Compare __x = _Compare()) noexcept {
  return std::map<_Key, _Mapped, _Compare>(__x);
}

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T2 &>() <
                              std::declval<const _T1 &>())>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y) noexcept {
  return __y < __x ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T2 &>(), std::declval<const _T1 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__y, __x) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp min(std::initializer_list<_Tp> __x) noexcept {
  return *std::min_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp min(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::min_element(__x.begin(), __x.end(), __comp);
}

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T1 &>() <
                              std::declval<const _T2 &>())>

constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y) noexcept {
  return __x < __y ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T1 &>(), std::declval<const _T2 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__x, __y) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp max(std::initializer_list<_Tp> __x) noexcept {
  return *std::max_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp max(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::max_element(__x.begin(), __x.end(), __comp);
}

template <typename _Tp> constexpr _Tp __bsf(_Tp __x) noexcept {
  return std::__countr_zero(__x);
}

template <typename _Tp> constexpr _Tp __bsr(_Tp __x) noexcept {
  return std::__bit_width(__x) - 1;
}

}  // namespace workspace
#line 6 "codeforces-workspace/contest/1511/f/f.cpp"
// #include "lib/cxx20"
#line 2 "Library/lib/direct"

/*
 * @file direct
 * @brief Pragma Directive
 */

#ifdef ONLINE_JUDGE

#pragma GCC optimize("O3")
#pragma GCC target("avx,avx2")
#pragma GCC optimize("unroll-loops")

#endif
#line 8 "codeforces-workspace/contest/1511/f/f.cpp"
// #include "lib/opt"
#line 2 "Library/src/sys/clock.hpp"

/*
 * @fn clock.hpp
 * @brief Clock
 */

#line 9 "Library/src/sys/clock.hpp"

namespace workspace {

using namespace std::chrono;

namespace internal {
// The start time of the program.
const auto start_time{system_clock::now()};
}  // namespace internal

/*
 * @fn elapsed
 * @return elapsed time of the program
 */
int64_t elapsed() {
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - internal::start_time).count();
}

}  // namespace workspace
#line 2 "Library/src/sys/ejection.hpp"

/**
 * @file ejection.hpp
 * @brief Ejection
 */

#line 9 "Library/src/sys/ejection.hpp"

namespace workspace {

namespace internal {

struct ejection {
  bool exit = 0;
};

}  // namespace internal

/**
 * @brief eject from a try block, throw nullptr
 * @param arg output
 */
template <class Tp> void eject(Tp const &arg) {
  std::cout << arg << "\n";
  throw internal::ejection{};
}

void exit() { throw internal::ejection{true}; }

}  // namespace workspace
#line 2 "Library/src/sys/iteration.hpp"

/**
 * @file iteration.hpp
 * @brief Case Iteration
 */

#line 9 "Library/src/sys/iteration.hpp"

#line 11 "Library/src/sys/iteration.hpp"

namespace workspace {

void main();

struct {
  // 1-indexed
  unsigned current{0};
  unsigned total{1};

  void read() { (std::cin >> total).ignore(); }

  int iterate() {
    static bool once = false;
    assert(!once);
    once = true;
    while (current++ < total) {
      try {
        main();
      } catch (internal::ejection const& status) {
        if (status.exit) break;
      }
    }
    return 0;
  }
} case_info;

}  // namespace workspace
#line 10 "codeforces-workspace/contest/1511/f/f.cpp"
// #include "lib/utils"

#line 2 "Library/src/utils/io/setup.hpp"

/**
 * @file setup.hpp
 * @brief I/O Setup
 */

#line 10 "Library/src/utils/io/setup.hpp"

namespace workspace {

/**
 * @brief Setup I/O.
 * @param __n Standard output precision
 */
void io_setup(int __n) {
  std::cin.tie(0)->sync_with_stdio(0);
  std::cout << std::fixed << std::setprecision(__n);

#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (std::cin >> bufc)
      std::cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}

}  // namespace workspace
#line 2 "Library/src/utils/py-like/range.hpp"

/**
 * @file range.hpp
 * @brief Range
 */

#line 9 "Library/src/utils/py-like/range.hpp"

#line 2 "Library/src/utils/iterator/reverse.hpp"

/*
 * @file reverse_iterator.hpp
 * @brief Reverse Iterator
 */

#if __cplusplus >= 201703L

#include <iterator>
#include <optional>

namespace workspace {

/*
 * @class reverse_iterator
 * @brief Wrapper class for `std::reverse_iterator`.
 * @see http://gcc.gnu.org/PR51823
 */
template <class Iterator>
class reverse_iterator : public std::reverse_iterator<Iterator> {
  using base_std = std::reverse_iterator<Iterator>;
  std::optional<typename base_std::value_type> deref;

 public:
  using base_std::reverse_iterator;

  constexpr typename base_std::reference operator*() noexcept {
    if (!deref) {
      Iterator tmp = base_std::current;
      deref = *--tmp;
    }
    return deref.value();
  }

  constexpr reverse_iterator &operator++() noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator &operator--() noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator operator++(int) noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
  constexpr reverse_iterator operator--(int) noexcept {
    base_std::operator++();
    deref.reset();
    return *this;
  }
};

}  // namespace workspace

#endif
#line 2 "Library/src/utils/py-like/reversed.hpp"

/**
 * @file reversed.hpp
 * @brief Reversed
 */

#include <initializer_list>
#line 10 "Library/src/utils/py-like/reversed.hpp"

namespace workspace {

namespace _reversed_impl {

template <class _Container> class reversed {
  _Container __cont;

 public:
  constexpr reversed(_Container &&__cont) noexcept : __cont(__cont) {}

  constexpr decltype(auto) begin() noexcept { return std::rbegin(__cont); }
  constexpr decltype(auto) begin() const noexcept {
    return std::rbegin(__cont);
  }

  constexpr decltype(auto) end() noexcept { return std::rend(__cont); }
  constexpr decltype(auto) end() const noexcept { return std::rend(__cont); }

  constexpr decltype(auto) size() const noexcept { return std::size(__cont); }
};

}  // namespace _reversed_impl

template <class _Container>
constexpr decltype(auto) reversed(_Container &&__cont) noexcept {
  return _reversed_impl::reversed<_Container>{std::forward<_Container>(__cont)};
}

template <class _Tp>
constexpr decltype(auto) reversed(
    std::initializer_list<_Tp> &&__cont) noexcept {
  return _reversed_impl::reversed<std::initializer_list<_Tp>>{
      std::forward<std::initializer_list<_Tp>>(__cont)};
}

}  // namespace workspace
#line 12 "Library/src/utils/py-like/range.hpp"

#if __cplusplus >= 201703L

namespace workspace {

template <class _Index> class range {
  _Index __first, __last;

 public:
  class iterator {
    _Index current;

   public:
    using difference_type = std::ptrdiff_t;
    using value_type = _Index;
    using reference = typename std::add_const<_Index>::type &;
    using pointer = iterator;
    using iterator_category = std::bidirectional_iterator_tag;

    constexpr iterator(const _Index &__i = _Index()) noexcept : current(__i) {}

    constexpr bool operator==(const iterator &__x) const noexcept {
      return current == __x.current;
    }
    constexpr bool operator!=(const iterator &__x) const noexcept {
      return current != __x.current;
    }

    constexpr iterator &operator++() noexcept {
      ++current;
      return *this;
    }
    constexpr iterator &operator--() noexcept {
      --current;
      return *this;
    }

    constexpr reference operator*() const noexcept { return current; }
  };

  constexpr range(_Index __first, _Index __last) noexcept
      : __first(__first), __last(__last) {}
  constexpr range(_Index __last) noexcept : __first(), __last(__last) {}

  constexpr iterator begin() const noexcept { return iterator{__first}; }
  constexpr iterator end() const noexcept { return iterator{__last}; }

  constexpr reverse_iterator<iterator> rbegin() const noexcept {
    return reverse_iterator<iterator>(end());
  }
  constexpr reverse_iterator<iterator> rend() const noexcept {
    return reverse_iterator<iterator>(begin());
  }

  constexpr size_t size() const noexcept {
    return std::distance(__first, __last);
  }
};

template <class... _Args>
constexpr decltype(auto) rrange(_Args &&...__args) noexcept {
  return reversed(range(std::forward<_Args>(__args)...));
}

}  // namespace workspace

#endif
#line 14 "codeforces-workspace/contest/1511/f/f.cpp"

signed main() {
  using namespace workspace;

  io_setup(15);

  /* given
    case_info.read();  //*/

  /* unspecified
    case_info.total = -1;  //*/

  return case_info.iterate();
}

#line 2 "Library/src/algebra/linear/matrix.hpp"

/**
 * @file matrix.hpp
 * @brief Matrix
 * @date 2021-02-15
 *
 *
 */

#line 13 "Library/src/algebra/linear/matrix.hpp"

namespace workspace {

/**
 * @brief Fixed size matrix.
 *
 * @tparam _Scalar
 * @tparam _Rows Number of rows
 * @tparam _Cols Number of columns
 */
template <class _Scalar, std::size_t _Rows = 0, std::size_t _Cols = _Rows>
class matrix {
 public:
  _Scalar __data[_Rows][_Cols] = {};

  using value_type = _Scalar;
  using size_type = std::size_t;

  constexpr static matrix eye() {
    static_assert(_Rows == _Cols);

    matrix __e;
    for (size_type __d = 0; __d != _Rows; ++__d) __e.__data[__d][__d] = 1;
    return __e;
  }

  constexpr operator decltype((__data))() { return __data; }
  constexpr operator decltype(std::declval<const matrix>().__data)
      const&() const {
    return __data;
  }

  constexpr auto begin() { return __data; }
  constexpr auto begin() const { return __data; }

  constexpr auto end() { return __data + _Rows; }
  constexpr auto end() const { return __data + _Rows; }

  constexpr size_type rows() const { return _Rows; }

  constexpr size_type cols() const { return _Cols; }

  constexpr auto transpose() const {
    matrix<_Scalar, _Cols, _Rows> __t;

    for (size_type __r = 0; __r != _Rows; ++__r)
      for (size_type __c = 0; __c != _Cols; ++__c)
        __t.__data[__c][__r] = __data[__r][__c];

    return __t;
  }

  constexpr matrix operator+() const { return *this; }

  constexpr matrix operator-() const {
    matrix __cp = *this;

    for (auto& __v : __cp.__data)
      for (auto& __e : __v) __e = -__e;

    return __cp;
  }

  template <class _Matrix> constexpr matrix& operator+=(const _Matrix& __x) {
    auto __m = std::min(_Rows, __x.rows());
    auto __n = std::min(_Cols, __x.cols());

    for (size_type __r = 0; __r != __m; ++__r)
      for (size_type __c = 0; __c != __n; ++__c)
        __data[__r][__c] += __x[__r][__c];

    return *this;
  }

  template <class _Matrix>
  constexpr matrix operator+(const _Matrix& __x) const {
    return matrix(*this) += __x;
  }

  template <class _Matrix> constexpr matrix& operator-=(const _Matrix& __x) {
    auto __m = std::min(_Rows, __x.rows());
    auto __n = std::min(_Cols, __x.cols());

    for (size_type __r = 0; __r != __m; ++__r)
      for (size_type __c = 0; __c != __n; ++__c)
        __data[__r][__c] -= __x[__r][__c];

    return *this;
  }

  template <class _Matrix>
  constexpr matrix operator-(const _Matrix& __x) const {
    return matrix(*this) -= __x;
  }

  template <class _Scalar2>
  constexpr matrix& operator*=(const matrix<_Scalar2, _Cols, _Cols>& __x) {
    if (this == &__x) return operator=(operator*(__x));

    for (auto& __r : __data) {
      _Scalar __tmp[_Cols] = {};

      auto __v = *__x.__data;
      for (auto& __w : __tmp) {
        auto __i = __v++;
        for (const auto& __e : __r) __w += __e * *__i, __i += _Cols;
      }

      auto __w = __tmp;
      for (auto& __e : __r) __e = std::move(*__w++);
    }

    return *this;
  }

  template <class _Scalar2, size_type _Rows2, size_type _Cols2>
  constexpr auto operator*(const matrix<_Scalar2, _Rows2, _Cols2>& __x) const {
    matrix<typename std::common_type<_Scalar, _Scalar2>::type, _Rows, _Cols2>
        __m;

    auto __w = *__m.__data;
    for (const auto& __r : __data)
      for (auto __v = *__x.__data, __v_end = __v + _Cols2; __v != __v_end;
           ++__w) {
        auto __i = __v++;
        for (auto __e = __r; __e != __r + std::min(_Cols, _Rows2); ++__e)
          *__w += *__e * *__i, __i += _Cols2;
      }

    return __m;
  }

  template <class _Matrix>
  constexpr
      typename std::enable_if<!std::is_convertible<_Matrix, value_type>::value,
                              matrix<_Scalar>>::type
      operator*(const _Matrix& __x) const {
    matrix<_Scalar> __m(_Rows, __x.cols());

    for (size_type __r = 0; __r != _Rows; ++__r)
      for (size_type __i = 0; __i != __x.cols(); ++__i)
        for (size_type __c = 0; __c != std::min(_Cols, __x.rows()); ++__c)
          __m[__r][__i] += __data[__r][__c] * __x[__c][__i];

    return __m;
  }

  constexpr matrix& operator*=(const value_type& __x) {
    for (auto& __v : __data)
      for (auto& __e : __v) __e *= __x;

    return *this;
  }

  constexpr matrix operator*(const value_type& __x) const {
    return matrix(*this) *= __x;
  }

  constexpr matrix& operator/=(const value_type& __x) {
    assert(__x != value_type(0));

    for (auto& __v : __data)
      for (auto& __e : __v) __e /= __x;

    return *this;
  }

  constexpr matrix operator/(const value_type& __x) const {
    return matrix(*this) /= __x;
  }

  template <class _Int> constexpr matrix pow(_Int __e) const {
    assert(0 <= __e);

    matrix __m = eye();
    for (matrix __cp = *this; __e; __cp *= __cp, __e >>= 1)
      if (__e & 1) __m *= __cp;

    return __m;
  }

  template <class _Os>
  constexpr friend _Os& operator<<(_Os& __os, const matrix& __x) {
    for (auto __i = __x.begin(); __i != __x.end(); ++__i, __os << '\n')
      for (size_type __c = 0; __c != _Cols; ++__c)
        __c ? void(__os << ' ') : (void)0, __os << *(*__i + __c);

    return __os;
  }
};  // namespace workspace

/**
 * @brief Dynamic matrix.
 *
 * @tparam _Scalar
 * @tparam _Rows Number of rows
 * @tparam _Cols Number of columns
 */
template <class _Scalar>
class matrix<_Scalar, 0, 0> : public std::valarray<std::valarray<_Scalar>> {
  using base = std::valarray<std::valarray<_Scalar>>;
  using row_type = typename base::value_type;

 public:
  using value_type = _Scalar;
  using size_type = std::size_t;

  using base::operator[];

  static matrix eye(size_type __n) {
    matrix __e(__n, __n);
    for (size_type __d = 0; __d != __n; ++__d) __e[__d][__d] = 1;
    return __e;
  }

  matrix() = default;

  matrix(size_type __n) : matrix(__n, __n) {}

  matrix(size_type __m, size_type __n) : base(row_type(__n), __m) {}

  template <class _Tp, typename = typename std::enable_if<
                           std::is_constructible<base, _Tp>::value &&
                           !std::is_constructible<size_type, _Tp>::value>::type>
  matrix(_Tp&& __x) : base(__x) {}

  matrix(std::initializer_list<row_type> __x) : base(__x) {}

  size_type rows() const { return base::size(); }

  size_type cols() const { return rows() ? operator[](0).size() : 0; }

  matrix transpose() const {
    matrix __t(cols(), rows());

    for (size_type __r = 0; __r != rows(); ++__r)
      for (size_type __c = 0; __c != cols(); ++__c)
        __t[__c][__r] = operator[](__r)[__c];

    return __t;
  }

  void resize(size_type __m, size_type __n) {
    matrix __t(__m, __n);

    if (rows() < __m) __m = rows();
    if (cols() < __n) __n = cols();

    for (size_type __r = 0; __r != __m; ++__r)
      for (size_type __c = 0; __c != __n; ++__c)
        __t[__r][__c] = std::move(operator[](__r)[__c]);

    base::swap(__t);
  }

  // binary operators {{

  template <class _Matrix, typename = void>
  struct is_valarray_based : std::false_type {};

  template <class _Matrix>
  struct is_valarray_based<
      _Matrix,
      typename std::enable_if<std::is_same<
          row_type, typename std::decay<decltype(
                        std::declval<_Matrix>()[0])>::type>::value>::type>
      : std::true_type {};

  template <class _Matrix>
  typename std::enable_if<!std::is_convertible<_Matrix, value_type>::value,
                          matrix&>::type
  operator*=(_Matrix&& __x) {
    return *this = operator*(std::forward<_Matrix>(__x));
  }

  template <class _Matrix>
  typename std::enable_if<!std::is_convertible<_Matrix, value_type>::value,
                          matrix>::type
  operator*(const _Matrix& __x) const {
    matrix __m(rows(), __x.cols());

    if constexpr (is_valarray_based<_Matrix>::value)
      for (size_type __r = 0; __r != rows(); ++__r)
        for (size_type __c = 0; __c != std::min(cols(), __x.rows()); ++__c)
          __m[__r] += operator[](__r)[__c] * __x[__c];

    else
      for (size_type __r = 0; __r != rows(); ++__r)
        for (size_type __i = 0; __i != __x.cols(); ++__i)
          for (size_type __c = 0; __c != std::min(cols(), __x.rows()); ++__c)
            __m[__r][__i] += operator[](__r)[__c] * __x[__c][__i];

    return __m;
  }

  matrix& operator*=(const value_type& __x) {
    for (size_type __r = 0; __r != rows(); ++__r)
      operator[](__r).operator*=(__x);

    return *this;
  }

  matrix operator*(const value_type& __x) const { return matrix(*this) *= __x; }

  friend matrix operator*(const value_type& __x, matrix __i) {
    for (size_type __r = 0; __r != __i.rows(); ++__r)
      __i.operator[](__r) = __x * __i.operator[](__r);

    return __i;
  }

  matrix& operator/=(const value_type& __x) {
    assert(__x != value_type(0));

    for (size_type __r = 0; __r != rows(); ++__r)
      operator[](__r).operator/=(__x);

    return *this;
  }

  matrix operator/(const value_type& __x) const { return matrix(*this) /= __x; }

  // }} binary operators

  template <class _Int> matrix pow(_Int __e) const {
    assert(0 <= __e);

    matrix __m = eye(rows());
    for (matrix __cp = *this; __e; __cp *= __cp, __e >>= 1)
      if (__e & 1) __m *= __cp;

    return __m;
  }

  // template <class _Is> friend _Is& operator>>(_Is& __is, matrix& __x) {
  //   for (size_type __r = 0; __r != __x.rows(); ++__r)
  //     for (size_type __c = 0; __c != __x.cols(); ++__c)
  //       __is >> __x.operator[](__r).operator[](__c);

  //   return __is;
  // }

  template <class _Os> friend _Os& operator<<(_Os& __os, const matrix& __x) {
    for (size_type __r = 0; __r != __x.rows(); ++__r, __os << '\n')
      for (size_type __c = 0; __c != __x.cols(); ++__c)
        __c ? void(__os << ' ') : (void)0,
            __os << __x.operator[](__r).operator[](__c);

    return __os;
  }
};

}  // namespace workspace
#line 2 "Library/src/modular/modint.hpp"

/**
 * @file modint.hpp
 *
 * @brief Modular Arithmetic
 */

#line 12 "Library/src/modular/modint.hpp"

#line 2 "Library/src/number_theory/sqrt_mod.hpp"

/**
 * @file sqrt_mod.hpp
 * @brief Tonelli-Shanks Algorithm
 */

#line 2 "Library/src/number_theory/pow_mod.hpp"

/**
 * @file mod_pow.hpp
 * @brief Modular Exponentiation
 */

#line 9 "Library/src/number_theory/pow_mod.hpp"

#line 2 "Library/src/utils/sfinae.hpp"

/**
 * @file sfinae.hpp
 * @brief SFINAE
 */

#line 10 "Library/src/utils/sfinae.hpp"
#include <type_traits>

#ifndef __INT128_DEFINED__

#ifdef __SIZEOF_INT128__
#define __INT128_DEFINED__ 1
#else
#define __INT128_DEFINED__ 0
#endif

#endif

namespace std {

#if __INT128_DEFINED__

template <> struct make_signed<__uint128_t> { using type = __int128_t; };
template <> struct make_signed<__int128_t> { using type = __int128_t; };

template <> struct make_unsigned<__uint128_t> { using type = __uint128_t; };
template <> struct make_unsigned<__int128_t> { using type = __uint128_t; };

template <> struct is_signed<__uint128_t> : std::false_type {};
template <> struct is_signed<__int128_t> : std::true_type {};

template <> struct is_unsigned<__uint128_t> : std::true_type {};
template <> struct is_unsigned<__int128_t> : std::false_type {};

#endif

}  // namespace std

namespace workspace {

template <class Tp, class... Args> struct variadic_front { using type = Tp; };

template <class... Args> struct variadic_back;

template <class Tp> struct variadic_back<Tp> { using type = Tp; };

template <class Tp, class... Args> struct variadic_back<Tp, Args...> {
  using type = typename variadic_back<Args...>::type;
};

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

/**
 * @brief Return type of subscripting ( @c [] ) access.
 */
template <class _Tp>
using subscripted_type =
    typename std::decay<decltype(std::declval<_Tp&>()[0])>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class _Tp, class = std::nullptr_t>
struct has_begin : std::false_type {};

template <class _Tp>
struct has_begin<_Tp, decltype(std::begin(std::declval<_Tp>()), nullptr)>
    : std::true_type {};

template <class _Tp, class = std::nullptr_t>
struct has_mod : std::false_type {};

template <class _Tp>
struct has_mod<_Tp, decltype(_Tp::mod, nullptr)> : std::true_type {};

template <class _Tp, class = void> struct is_integral_ext : std::false_type {};
template <class _Tp>
struct is_integral_ext<
    _Tp, typename std::enable_if<std::is_integral<_Tp>::value>::type>
    : std::true_type {};

#if __INT128_DEFINED__

template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};

#endif

#if __cplusplus >= 201402

template <class _Tp>
constexpr static bool is_integral_ext_v = is_integral_ext<_Tp>::value;

#endif

template <typename _Tp, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename _Tp>
struct multiplicable_uint<
    _Tp,
    typename std::enable_if<(2 < sizeof(_Tp)) &&
                            (!__INT128_DEFINED__ || sizeof(_Tp) <= 4)>::type> {
  using type = uint_least64_t;
};

#if __INT128_DEFINED__

template <typename _Tp>
struct multiplicable_uint<_Tp,
                          typename std::enable_if<(4 < sizeof(_Tp))>::type> {
  using type = __uint128_t;
};

#endif

template <typename _Tp> struct multiplicable_int {
  using type =
      typename std::make_signed<typename multiplicable_uint<_Tp>::type>::type;
};

template <typename _Tp> struct multiplicable {
  using type = std::conditional_t<
      is_integral_ext<_Tp>::value,
      std::conditional_t<std::is_signed<_Tp>::value,
                         typename multiplicable_int<_Tp>::type,
                         typename multiplicable_uint<_Tp>::type>,
      _Tp>;
};

}  // namespace workspace
#line 11 "Library/src/number_theory/pow_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular exponentiation.
 *
 * @param __x
 * @param __n Exponent
 * @param __mod Modulus
 * @return
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> pow_mod(
    _Tp __x, _Tp __n, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  mul_type __y{1};

  while (__n) {
    if (__n & 1) (__y *= __x) %= __mod;
    __x = (mul_type)__x * __x % __mod;
    __n >>= 1;
  }

  return __y;
};

}  // namespace workspace
#line 10 "Library/src/number_theory/sqrt_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular square root.
 *
 * @param __x
 * @param __mod Modulus
 * @return One if it exists. Otherwise -1.
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> sqrt_mod(
    _Tp __x, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  if (!__x) return 0;

  if (__mod == 2) return __x;

  if (pow_mod(__x, __mod >> 1, __mod) != 1) return -1;

  _Tp __z = __builtin_ctz(__mod - 1), __q = __mod >> __z;

  mul_type __a = pow_mod(__x, (__q + 1) >> 1, __mod), __b = 2;
  while (pow_mod<_Tp>(__b, __mod >> 1, __mod) == 1) ++__b;
  __b = pow_mod<_Tp>(__b, __q, __mod);

  _Tp __shift = 0;

  for (auto __r = __a * __a % __mod * pow_mod(__x, __mod - 2, __mod) % __mod;
       __r != 1; (__r *= (__b *= __b) %= __mod) %= __mod) {
    auto __bsf = __z;

    for (auto __e = __r; __e != 1; --__bsf) (__e *= __e) %= __mod;

    while (++__shift != __bsf) (__b *= __b) %= __mod;

    (__a *= __b) %= __mod;
  }

  return __a;
};

}  // namespace workspace
#line 15 "Library/src/modular/modint.hpp"

namespace workspace {

namespace _modint_impl {

/**
 * @brief Modular arithmetic.
 *
 * @tparam Mod identifier, which represents modulus if positive
 * @tparam Storage Reserved size for inverse calculation
 */
template <auto Mod, unsigned Storage> struct modint {
  static_assert(is_integral_ext<decltype(Mod)>::value,
                "Mod must be integral type.");

  using mod_type = typename std::make_signed<typename std::conditional<
      0 < Mod, typename std::add_const<decltype(Mod)>::type,
      decltype(Mod)>::type>::type;

  using value_type = typename std::decay<mod_type>::type;

  using mul_type = typename multiplicable_uint<value_type>::type;

  // Modulus
  static mod_type mod;

  static unsigned storage;

  constexpr static void reserve(unsigned __n) noexcept { storage = __n; }

 private:
  value_type value = 0;

  struct direct_ctor_t {};
  constexpr static direct_ctor_t direct_ctor_tag{};

  // Direct constructor
  template <class _Tp> constexpr modint(_Tp __n, direct_ctor_t) : value(__n) {}

 public:
  constexpr modint() noexcept = default;

  template <class _Tp, typename std::enable_if<
                           is_integral_ext<_Tp>::value>::type * = nullptr>
  constexpr modint(_Tp __n) noexcept
      : value((__n %= mod) < 0 ? __n += mod : __n) {}

  constexpr modint(bool __n) noexcept : value(__n) {}

  constexpr operator value_type() const noexcept { return value; }

  constexpr static modint one() noexcept { return 1; }

  // unary operators {{
  constexpr modint operator++(int) noexcept {
    modint __t{*this};
    operator++();
    return __t;
  }

  constexpr modint operator--(int) noexcept {
    modint __t{*this};
    operator--();
    return __t;
  }

  constexpr modint &operator++() noexcept {
    if (++value == mod) value = 0;
    return *this;
  }

  constexpr modint &operator--() noexcept {
    if (!value)
      value = mod - 1;
    else
      --value;
    return *this;
  }

  constexpr modint operator+() const noexcept { return *this; }

  constexpr modint operator-() const noexcept {
    return {value ? mod - value : 0, direct_ctor_tag};
  }

  // }} unary operators

  // operator+= {{

  constexpr modint &operator+=(const modint &__x) noexcept {
    if ((value += __x.value) >= mod) value -= mod;
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator+=(_Tp const &__x) noexcept {
    if (((value += __x) %= mod) < 0) value += mod;
    return *this;
  }

  // }} operator+=

  // operator+ {{

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator+(_Tp const &__x) const noexcept {
    return modint{*this} += __x;
  }

  constexpr modint operator+(modint __x) const noexcept { return __x += *this; }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator+(_Tp const &__x, modint __y) noexcept {
    return __y += __x;
  }

  // }} operator+

  // operator-= {{

  constexpr modint &operator-=(const modint &__x) noexcept {
    if ((value -= __x.value) < 0) value += mod;
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator-=(_Tp __x) noexcept {
    if (((value -= __x) %= mod) < 0) value += mod;
    return *this;
  }

  // }} operator-=

  // operator- {{

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator-(_Tp const &__x) const noexcept {
    return modint{*this} -= __x;
  }

  constexpr modint operator-(const modint &__x) const noexcept {
    return modint{*this} -= __x;
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator-(_Tp __x, const modint &__y) noexcept {
    if (((__x -= __y.value) %= mod) < 0) __x += mod;
    return {__x, direct_ctor_tag};
  }

  // }} operator-

  // operator*= {{

  constexpr modint &operator*=(const modint &__x) noexcept {
    value =
        static_cast<value_type>(value * static_cast<mul_type>(__x.value) % mod);
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator*=(_Tp __x) noexcept {
    value = static_cast<value_type>(
        value * mul_type((__x %= mod) < 0 ? __x + mod : __x) % mod);
    return *this;
  }

  // }} operator*=

  // operator* {{

  constexpr modint operator*(const modint &__x) const noexcept {
    return {static_cast<mul_type>(value) * __x.value % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator*(_Tp __x) const noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(value) * __x % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator*(_Tp __x, const modint &__y) noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(__x) * __y.value % mod, direct_ctor_tag};
  }

  // }} operator*

 protected:
  static value_type _mem(value_type __x) {
    static std::vector<value_type> __m{0, 1};
    static value_type __i = (__m.reserve(Storage), 1);
    while (__i < __x) {
      ++__i;
      __m.emplace_back(mod - mul_type(mod / __i) * __m[mod % __i] % mod);
    }
    return __m[__x];
  }

  template <class _Tp>
  constexpr static
      typename std::enable_if<is_integral_ext<_Tp>::value, value_type>::type
      _div(mul_type __r, _Tp __x) noexcept {
    assert(__x != _Tp(0));
    if (!__r) return 0;

    std::make_signed_t<_Tp> __v{};
    bool __neg = __x < 0 ? __x = -__x, true : false;

    if (static_cast<decltype(storage)>(__x) < storage)
      __v = _mem(__x);
    else {
      decltype(__v) __y{mod}, __u{1}, __t;

      while (__x)
        __t = __y / __x, __y ^= __x ^= (__y -= __t * __x) ^= __x,
        __v ^= __u ^= (__v -= __t * __u) ^= __u;

      if (__y < 0) __neg ^= 1;
    }

    if (__neg)
      __v = 0 < __v ? mod - __v : -__v;
    else if (__v < 0)
      __v += mod;

    return __r == mul_type(1) ? static_cast<value_type>(__v)
                              : static_cast<value_type>(__r * __v % mod);
  }

 public:
  // operator/= {{

  constexpr modint &operator/=(const modint &__x) noexcept {
    if (value) value = _div(value, __x.value);
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator/=(_Tp __x) noexcept {
    if (value) value = _div(value, __x %= mod);
    return *this;
  }

  // }} operator/=

  // operator/ {{

  constexpr modint operator/(const modint &__x) const noexcept {
    if (!value) return {};
    return {_div(value, __x.value), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator/(_Tp __x) const noexcept {
    if (!value) return {};
    return {_div(value, __x %= mod), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator/(_Tp __x, const modint &__y) noexcept {
    if (!__x) return {};
    if ((__x %= mod) < 0) __x += mod;
    return {_div(__x, __y.value), direct_ctor_tag};
  }

  // }} operator/

  constexpr modint inv() const noexcept { return _div(1, value); }

  template <class _Tp>
  constexpr std::__enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      _Tp __e) const noexcept {
    modint __r{1, direct_ctor_tag};

    for (modint __b{__e < 0 ? __e = -__e, _div(1, value) : value,
                              direct_ctor_tag};
         __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  template <class _Tp>
  friend constexpr std::__enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      modint __b, _Tp __e) noexcept {
    if (__e < 0) {
      __e = -__e;
      __b.value = _div(1, __b.value);
    }

    modint __r{1, direct_ctor_tag};

    for (; __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  constexpr modint sqrt() const noexcept {
    return {sqrt_mod(value, mod), direct_ctor_tag};
  }

  friend constexpr modint sqrt(const modint &__x) noexcept {
    return {sqrt_mod(__x.value, mod), direct_ctor_tag};
  }

  template <class _Os>
  friend _Os &operator<<(_Os &__os, const modint &__x) noexcept {
    return __os << __x.value;
  }

  friend std::istream &operator>>(std::istream &__is, modint &__x) noexcept {
    std::string __s;
    __is >> __s;
    bool __neg = false;
    if (__s.front() == '-') {
      __neg = true;
      __s.erase(__s.begin());
    }
    __x = 0;
    for (char __c : __s) __x = __x * 10 + (__c - '0');
    if (__neg) __x = -__x;
    return __is;
  }
};

template <auto Mod, unsigned Storage>
typename modint<Mod, Storage>::mod_type modint<Mod, Storage>::mod =
    Mod > 0 ? Mod : 0;

template <auto Mod, unsigned Storage>
unsigned modint<Mod, Storage>::storage = Storage;

}  // namespace _modint_impl

/**
 * @brief Modular arithmetic.
 *
 * @tparam Mod modulus
 * @tparam Storage Reserved size for inverse calculation
 */
template <auto Mod, unsigned Storage = 0,
          typename std::enable_if<(Mod > 0)>::type * = nullptr>
using modint = _modint_impl::modint<Mod, Storage>;

/**
 * @brief Runtime modular arithmetic.
 *
 * @tparam type_id uniquely assigned
 * @tparam Storage Reserved size for inverse calculation
 */
template <unsigned type_id = 0, unsigned Storage = 0>
using modint_runtime = _modint_impl::modint<-(signed)type_id, Storage>;

// #define modint_newtype modint_runtime<__COUNTER__>

}  // namespace workspace
#line 31 "codeforces-workspace/contest/1511/f/f.cpp"

namespace workspace {

using mint = modint<998244353>;
using mat = matrix<mint>;

void main() {
  // start here!

  int n, k;
  cin >> n >> k;

  vector<string> wds(n), sufs{""};
  for (auto &&x : wds) {
    cin >> x;
  }
  sort(begin(wds), end(wds));

  do {
    string c;
    for (auto &&x : wds) {
      c += x;
    }
    for (auto i : range(c.size())) {
      for (auto l : range(5)) {
        if (i + l > c.size()) {
          break;
        }
        sufs.emplace_back(c.substr(i, l));
      }
    }
  } while (next_permutation(begin(wds), end(wds)));

  sort(begin(sufs), end(sufs));
  sufs.erase(unique(begin(sufs), end(sufs)), end(sufs));

  const auto m = sufs.size();
  mat a(m * 5);

  for (auto i : range(4)) {
    for (auto j : range(m)) {
      a[i * m + j][(i + 1) * m + j] = 1;
    }
  }

  for (auto j : range(m)) {
    for (auto w : wds) {
      auto len = w.size();
      w = sufs[j] + w;
      vector<mint> dp(w.size() + 1);
      dp[0] = 1;
      for (auto i : range(w.size())) {
        for (auto &&x : wds) {
          if (!i && x.size() <= sufs[j].size()) {
            continue;
          }
          if (w.substr(i, x.size()) == x) dp[i + x.size()] += dp[i];
        }
      }
      for (auto i : range(w.size() + 1)) {
        auto enc =
            lower_bound(begin(sufs), end(sufs), w.substr(i)) - begin(sufs);
        if (enc != sufs.size()) a[(len - 1) * m + j][enc] += dp[i];
      }
    }
  }

  a = a.pow(k);
  cout << a[0][0] << "\n";
}

}  // namespace workspace

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 8 + 5;
const int MAXL = 5 + 5;
const int mod = 998244353;

inline void add_mod(int &a,int b){ a+=b; if(a>=mod) a-=mod;}

inline ll pw(ll a,ll b)
{
	ll res = 1;
	while(b)
	{
		if(b&1) res=res*a%mod;
		a=a*a%mod; b>>=1;
	}
	return res;
}

vector<int> Berlekamp_Massey(const vector<int> &a)
{
	int n = (int)a.size(), len = 0, m = 0, ld = 1;
	vector<int> res(n), lst(n), tmp;
	res[0] = lst[0] = 1;
	for(int i=0; i<n; ++i)
	{
		++m;
		int d = a[i];
		for(int j=1; j<=len; ++j) d = (d + (ll)res[j] * a[i - j]) %mod;
		if(!d) continue;
		tmp = res;
		ll mul = d * pw(ld, mod - 2) %mod;
		for(int j=m; j<n; ++j) res[j] = (res[j] - mul * lst[j - m]) %mod;
		if((len << 1) > i) continue;
		len = i + 1 - len;
		ld = d; lst = tmp; m = 0;
	}

	res.resize(len+1);
	res.erase(res.begin());
	for(int i=0; i<(int)res.size(); ++i) add_mod(res[i] = -res[i], mod);
	return res;
}

namespace Linear_Rec
{
	inline vector<int> combine(const vector<int> &a,const vector<int> &b,const vector<int> &tr)
	{
		vector<int> res((int)a.size() + (int)b.size() - 1);
		for(int i=0; i<(int)a.size(); ++i)
			for(int j=0; j<(int)b.size(); ++j)
				res[i+j] = (res[i+j] + (ll)a[i] * b[j]) %mod;
		for(int i=(int)res.size()-1; i>=(int)tr.size(); --i)
			for(int j=0; j<(int)tr.size(); ++j)
				add_mod(res[i - j - 1], (ll)res[i] * tr[j] %mod);
		res.resize(tr.size());
		return res;
	}
}

inline int linear_rec(const vector<int> &s,const vector<int> &tr,int k)
{
	using namespace Linear_Rec;

	int n = (int)tr.size();
	vector<int> res(n), a(n);
	res[0] = a[1] = 1;
	while(k)
	{
		if(k&1) res=combine(res,a,tr);
		a=combine(a,a,tr); k>>=1;
	}

	int ans = 0;
	for(int i=0; i<(int)tr.size(); ++i)
		ans = (ans + (ll)res[i] * s[i]) %mod;
	return ans;
}

char s[MAXN][MAXL];
int len[MAXN];

const int lim = 1e2;
const int LIM = lim + 5;

int f[LIM][MAXN][MAXL];
vector< pair<int,pii> > to[MAXN][MAXL];

inline bool chk_suf(int x,int l,int y)
{
	for(int i=len[x]-l+1, j=1; i<=len[x] && j<=len[y]; ++i, ++j)
		if(s[x][i] != s[y][j]) return 0;
	return 1;
}

inline pair<int,pii> get_nxt(int x,int xl,int y,int yl)
{
	if(xl == yl)
		return make_pair(xl, make_pair(0, 0));
	else if(xl < yl)
		return make_pair(xl, make_pair(y, yl - xl));
	else
		return make_pair(yl, make_pair(x, xl - yl));
}

int main(void)
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; ++i)
		scanf("%s",s[i]+1), len[i] = strlen(s[i] + 1);

	for(int i=1; i<=n; ++i)
		for(int j=1; j<len[i]; ++j)
			for(int k=1; k<=n; ++k) if(chk_suf(i,j,k))
				to[i][j].push_back(get_nxt(i, j, k, len[k]));

	for(int i=1; i<=n; ++i)
		for(int j=1; j<=n; ++j) if(chk_suf(i,len[i],j))
			to[0][0].push_back(get_nxt(i, len[i], j, len[j]));

	f[0][0][0] = 1;
	for(int i=0; i<lim; ++i)
		for(int j=0; j<=n; ++j)
		{
			int kl = j? 1: 0, kr = j? len[j]-1: 0;
			for(int k=kl; k<=kr; ++k) if(f[i][j][k])
			{
				vector< pair<int,pii> > &vec = to[j][k];
				for(int it=0; it<(int)vec.size(); ++it)
				{
					int ii = i + vec[it].first, jj = vec[it].second.first, kk = vec[it].second.second;
					if(ii < lim)
						add_mod(f[ii][jj][kk], f[i][j][k]);
				}
			}
		}
	vector<int> g(lim);
	for(int i=0; i<lim; ++i) g[i] = f[i][0][0];

	printf("%d",linear_rec(g, Berlekamp_Massey(g), m));
	return 0;
}

#include<bits/stdc++.h>
#define L(i, j, k) for(int i = j, i##E = k; i <= i##E; i++)
#define R(i, j, k) for(int i = j, i##E = k; i >= i##E; i--)
#define ll long long
#define pii pair<int, int>
#define db double
#define x first
#define y second
#define sz(a) ((int) (a).size())
#define mkp make_pair
#define vi vector<int>
using namespace std;
const int N = 307, mod = 998244353;
int all = 1, tot;
struct Martix {
	int G[N][N];
	void clear() { L(i, 1, tot) L(j, 1, tot) G[i][j] = 0; }
	void start() { clear(); L(i, 1, tot) G[i][i] = 1; }
} P;
Martix operator * (Martix aa, Martix bb) {
	Martix res; res.clear();
	L(i, 1, tot) L(j, 1, tot) L(k, 1, tot) (res.G[i][j] += (ll) aa.G[i][k] * bb.G[k][j] % mod) %= mod;
	return res;
}
Martix operator ^ (Martix aa, int bb)  {
	Martix res; res.start();
	for(; bb; aa = aa * aa, bb >>= 1) if(bb & 1) res = res * aa;
	return res;
}
int n, m, Len, ch[N][26], fa[N], Cnt[N];
char s[N];
int Vis[N][N], f[N][2];
queue< int > q;
int get(int x, int y) {
	if(!Vis[x][y]) Vis[x][y] = ++tot, f[tot][0] = x, f[tot][1] = y, q.push(tot);
	return Vis[x][y];
}
void getEdge() {
	get(1, 1);
	while( !q.empty() ) {
		int u = q.front(), s1 = f[u][0], s2 = f[u][1];
		q.pop();
		L(i, 0, 25) if(ch[s1][i] && ch[s2][i]) {
			P.G[u][get(ch[s1][i], ch[s2][i])] = 1;
			P.G[u][get(ch[s1][i], 1)] = Cnt[ch[s2][i]];
			P.G[u][get(1, ch[s2][i])] = Cnt[ch[s1][i]];
			P.G[u][get(1, 1)] = Cnt[ch[s1][i]] * Cnt[ch[s2][i]];
		}
	}
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> m;
	L(i, 1, n) {
		cin >> (s + 1), Len = strlen(s + 1);
		int now = 1;
		L(j, 1, Len) {
			if(!ch[now][s[j] - 'a']) ch[now][s[j] - 'a'] = ++all;
			now = ch[now][s[j] - 'a'];
		}
		Cnt[now] ++;
	}
	getEdge();
	cout << (P ^ m).G[1][1] << "\n";
	return 0;
}
// To Cheat, To attack!

#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define uid uniform_int_distribution
#define uint unsigned int
#define ld long double
#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define ar array
#define f first
#define s second
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rint(l, r) uid<int>(l, r)(rng)
template<class T> using pq = priority_queue<T>;
template<class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}
template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.f); cerr << ','; __print(x.s); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif
template <int MOD_> struct modnum {
    static constexpr int MOD = MOD_;

    int v;

    modnum() : v(0) {}
    modnum(ll v_) : v(int(v_ % MOD)) { if (v < 0) v += MOD; }
    explicit operator int() const { return v; }
    explicit operator bool() const { return v; }

    friend ostream& operator << (ostream& out, const modnum& n) { return out << int(n); }
    friend istream& operator >> (istream& in, modnum& n) { ll v_; in >> v_; n = modnum(v_); return in; }

    friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
    friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }
    friend bool operator ! (const modnum &a) { return a.v == 0; }

    modnum operator- () const {
        return neg();
    }
    modnum operator+ () const {
        return modnum(*this);
    }

    modnum& operator ++ () {
        v++;
        if (v == MOD) v = 0;
        return *this;
    }
    modnum& operator -- () {
        if (v == 0) v = MOD;
        v--;
        return *this;
    }
    modnum& operator += (const modnum& o) {
        v -= MOD-o.v;
        v = (v < 0) ? v + MOD : v;
        return *this;
    }
    modnum& operator -= (const modnum& o) {
        v -= o.v;
        v = (v < 0) ? v + MOD : v;
        return *this;
    }
    modnum& operator *= (const modnum& o) {
        v = int((ll) v * o.v % MOD);
        return *this;
    }

    friend modnum binpow(modnum a, ll p) {
        if (p == 0) return 1;
        modnum ret = 1;
        for (; p; p /= 2, a *= a) if (p&1) ret *= a;
        return ret;
    }

    modnum inv() const {
        return binpow(*this, MOD-2);
    }
    friend modnum inv(const modnum& m) { return m.inv(); }

    modnum& operator /= (const modnum& o) {
        return *this *= o.inv();
    }

    modnum neg() const {
        modnum res;
        res.v = v ? MOD-v : 0;
        return res;
    }
    friend modnum neg(const modnum& m) { return m.neg(); }

    friend modnum operator ++ (modnum& a, int) { modnum r = a; ++a; return r; }
    friend modnum operator -- (modnum& a, int) { modnum r = a; --a; return r; }
    friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
    friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
    friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }
    friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= b; }
};

const int mod = 998244353;
using mint = modnum<mod>;

void __print(mint x) {cerr << x;}

vector<mint> facs, invfacs;

mint choose(const mint &a, const mint &b) {
    int _a = (int)a, _b = (int)b;
    if (_b > _a || _a < 0 || _b < 0) return 0;
    return facs[_a] * invfacs[_b] * invfacs[_a-_b];
}

void finit(const int nx) {
    facs.resize(nx+1);
    invfacs.resize(nx+1);
    facs[0] = facs[1] = invfacs[0] = invfacs[1] = 1;
    for (int i = 2; i <= nx; i++) {
        facs[i] = facs[i-1] * i;
    }
    invfacs[nx] = inv(facs[nx]);
    for (int i = nx-1; i > 1; i--) {
        invfacs[i] = invfacs[i+1] * (i+1);
    }
}

int NX;
struct Matrix {
    vector<vector<mint>> t;
    Matrix() : t(vector<vector<mint>>(NX, vector<mint>(NX))) {}
    Matrix operator * (const Matrix &other) {
        Matrix res;
        for (int i = 0; i < NX; i++) {
            for (int j = 0; j < NX; j++) {
                for (int k = 0; k < NX; k++) {
                    res.t[i][k] += t[i][j] * other.t[j][k];
                }
            }
        }
        return res;
    }
    void operator *= (const Matrix &other) {
        *this = *this * other;
    }
    void operator ^= (ll k) {
        assert(k >= 0);
        Matrix res;
        for (int i = 0; i < NX; i++) res.t[i][i] = 1;
        while (k) {
            if (k&1) res *= *this;
            *this *= *this;
            k >>= 1;
        }
        *this = res;
    }
};

void test_case() {
    int a, b; cin >> a >> b;
    vector<string> t(a);
    for (auto &x : t) cin >> x;
    vector<string> each = {""};
    for (int i = 0; i < a; i++) {
        string cur;
        for (int j = 0; j < sz(t[i]); j++) {
            cur += t[i][j];
            each.push_back(cur);
        }
    }
    sort(all(each));
    each.erase(unique(all(each)), each.end());
    const int N = sz(each);
    map<string, int> mp;
    for (int i = 0; i < N; i++) {
        mp[each[i]] = i;
    }
    vector<bool> skip(N);
    for (int j = 0; j < N; j++) {
        skip[j] = find(all(t), each[j]) != t.end();
    }
    vector<vector<bool>> vis(N, vector<bool>(N)), good(N, vector<bool>(N));
    good[0][0] = 1;
    vector<pii> ok;
    vector<int> states;
    auto turn = [&](int x, int y) {
        states.push_back(x*N+y);
        return x*N+y;
    };
    for (int i = 0; i < min(10, b); i++) {
        for (int j = 0; j < N; j++) {
            for (int k = 0; k < N; k++) {
                if (good[j][k] && !vis[j][k]) {
                    vis[j][k] = 1;
                    for (char l = 'a'; l <= 'z'; l++) {
                        if (!mp.count(each[j] + l) || !mp.count(each[k] + l)) continue;
                        int pos1 = mp[each[j] + l];
                        int pos2 = mp[each[k] + l];
                        int _p = turn(j, k);
                        if (skip[pos1]) good[0][pos2] = good[0][pos2]||good[j][k], ok.push_back({_p, turn(0, pos2)});
                        if (skip[pos2]) good[pos1][0] = good[pos1][0]||good[j][k], ok.push_back({_p, turn(pos1, 0)});
                        if (skip[pos1]&&skip[pos2]) good[0][0] = good[0][0]||good[j][k], ok.push_back({_p, turn(0, 0)});
                        good[pos1][pos2] = good[pos1][pos2]||good[j][k];
                        ok.push_back({_p, turn(pos1, pos2)});
                    }
                }
            }
        }
    }
    sort(all(states));
    states.erase(unique(all(states)), states.end());
    NX = sz(states);
    Matrix first, expo;
    sort(all(ok));
    for (int i = 0; i < sz(ok); i++) {
        int r = i;
        while (r+1<sz(ok)&&ok[r+1]==ok[r]) r++;
        auto [x, y] = ok[i];
        int _x = lower_bound(all(states), x) - states.begin();
        int _y = lower_bound(all(states), y) - states.begin();
        expo.t[_x][_y] = r-i+1;
        i = r;
    }
    first.t[0][0] = 1;
    expo ^= b;
    first *= expo;
    cout << first.t[0][0] << '\n';
}
int main() {
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
//    cin >> t;
    while (t--) test_case();
}

#include <bits/stdc++.h>
using namespace std;

#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
#define debug(...) do {cerr<<__LINE__<<" : ("#__VA_ARGS__<<") = "; Out(__VA_ARGS__); cerr<<flush;} while(0)
template <typename T> void Out(T x) {cerr<<x<<"\n";}
template <typename T,typename ...I> void Out(T x,I ...NEXT) {cerr<<x<<", "; Out(NEXT...);}

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}

const int mod=998244353,bas=42;

inline void inc(int &x,int y) {
	x=x+y;
	if(x>=mod) x=x-mod;
}

struct Mat {
	int n,m; long long a[165][165];
	Mat() {n=m=0,memset(a,0,sizeof a);}

	Mat operator * (const Mat &t) const {
		Mat r; r.n=n,r.m=t.m;
		rep(i,1,n) rep(j,1,m)
			if(a[i][j]) rep(k,1,r.m)
				r.a[i][k]=(r.a[i][k]+a[i][j]*t.a[j][k])%mod;
		return r;
	}
} per,O;
struct Tree {
	int to[26],en;
} t[50];
int n,m,dot,mp[2000],fk[205];
char in[10];

Mat qkpow(int y) {
	Mat r; r.n=r.m=per.n;
	rep(i,1,r.n) r.a[i][i]=1;
	while(y) {
		if(y&1) r=r*per;
		per=per*per; y>>=1;
	}
	return r;
}

void ins() {
	int p=0;
	scanf("%s",in+1);
	rep(i,1,strlen(in+1)) {
		int d=in[i]-'a';
		if(!t[p].to[d])
			t[p].to[d]=++dot;
		p=t[p].to[d];
	}
	t[p].en=1;
}

int dfs(int u,int v) {
	if(u>v) swap(u,v);
	if(mp[u*bas+v]) return mp[u*bas+v];
	mp[u*bas+v]=++per.n,fk[per.n]=(t[u].en&t[v].en);
	int ids,id=per.n;
	rep(i,0,25) {
		if(t[0].to[i]) {
			if(t[u].en and t[v].to[i]) {
				ids=dfs(t[0].to[i],t[v].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].en and t[v].en) {
				ids=dfs(t[0].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
			if(t[u].to[i] and t[v].en) {
				ids=dfs(t[u].to[i],t[0].to[i]);
				per.a[id][ids]=1;
			}
		}
		if(t[u].to[i] and t[v].to[i]) {
			ids=dfs(t[u].to[i],t[v].to[i]);
			per.a[id][ids]=1;
		}
	}
	return id;
}

int main() {
	n=read(9),m=read(9);
	rep(i,1,n) ins();
	rep(i,0,25) if(t[0].to[i]) {
		dfs(t[0].to[i],t[0].to[i]);
		O.a[1][mp[t[0].to[i]*bas+t[0].to[i]]]=1;
	}
	O.m=per.m=per.n,O.n=1;
	O=O*qkpow(m-1);
	int ans=0;
	rep(i,1,per.n)
		if(fk[i]) inc(ans,O.a[1][i]);
	print(ans,'\n');
	return 0;
} // OOO

#include<bits/stdc++.h>
using namespace std;
const int N=1700,mod=998244353;
int g[N][N],n,m,f[N];
char s[N];
int tr[N][26],v[N],num=1;
inline int pos(int x,int y) { return (x-1)*num+y;}
void ins() {
	int u=1;
	scanf("%s",s+1);int len=strlen(s+1);
	for(int i=1;i<=len;i++) {
		int x=s[i]-'a';
		if(tr[u][x]) u=tr[u][x];
		else u=tr[u][x]=++num;
	}
	v[u]=1;
}

void mult(int A[N],int B[N][N]) {
	int C[N];memset(C,0,sizeof(C));
	for(int i=1;i<=num;i++)
		if(A[i]) for(int j=1;j<=num;j++)
			C[j]=(C[j]+(1ll)*A[i]*B[i][j])%mod;
	memcpy(A,C,sizeof(C));
}
void mulf(int A[N][N],int B[N][N]) {
	int C[N][N];memset(C,0,sizeof(C));
	for(int i=1;i<=num;i++)
		for(int j=1;j<=num;j++)
			if(A[i][j]) for(int k=1;k<=num;k++)
				C[i][k]=(C[i][k]+(1ll)*A[i][j]*B[j][k])%mod;
	memcpy(A,C,sizeof(C));
}

int main() {
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) ins();
	f[1]=1;
//	cout<<"? "<<num<<"\n";
	for(int i=1;i<=num;i++) {
		for(int j=1;j<=num;j++) {
			for(int a=0;a<=25;a++) {
				if(!tr[i][a]) continue;
				int b=a;
				if(!tr[j][b]) continue;
	//			cout<<i<<" "<<j<<" "<<tr[i][a]<<" "<<tr[j][b]<<" "<<pos(i,j)<<" "<<pos(tr[i][a],tr[j][b])<<"\n";
				g[pos(i,j)][pos(tr[i][a],tr[j][b])]=1;
				if(v[tr[i][a]]) g[pos(i,j)][pos(1,tr[j][b])]=1;
				if(v[tr[j][b]]) g[pos(i,j)][pos(tr[i][a],1)]=1;
				if(v[tr[i][a]] && v[tr[j][b]]) g[pos(i,j)][1]=1;
			}
		}
	}
	num*=num;
/*	for(int i=1;i<=num;i++) {
		for(int j=1;j<=num;j++) {
			cout<<g[i][j]<<" ";
		}
		cout<<endl;
	}*/
	while(m) {
		if(m&1) mult(f,g);
		mulf(g,g);m>>=1;
	}
	cout<<f[1]<<"\n";
	return 0;
}

#include<bits/stdc++.h>

using namespace std;

#define pb push_back
#define F first
#define S second
#define debug(x) cour<<#x<<" :"<<x<<"\n"
#define all(x) x.begin(),x.end()
#define pii pair<int,int>
#define FAST ios_base::sync_with_stdio(false), cin.tie(), cout.tie();
//#define int long long

typedef long long ll;
typedef long double ld;

const int maxn = 5e1 + 7;
const int maxm = 210 + 7;
const int mod = 998244353;
const int INF = 1e9 + 7;
const int maxk = 26;
const int mlog = 20;
const int SQ = 400;

struct MAT { int mat[maxm][maxm]; };
MAT ans;

int n, m;
int mp[maxm][maxm];

int ncnt, mcnt;
int trie[maxn][maxk];

int cnt[maxn];

inline int add(string s)
{
	int cur = 0;
	for(int i = 0; i < s.size(); i++)
	{
		int ch = s[i] - 'a';
		if(!trie[cur][ch]) trie[cur][ch] = ++ncnt;
		cur = trie[cur][ch];
	}

	return cur;
}

int dfs(int x,int y)
{
	if(mp[x][y] != -1) return mp[x][y];
	mp[x][y] = ++mcnt;
	int base = mcnt;

	for(int i = 0; i < maxk; i++)
	{
		if(trie[x][i] && trie[y][i])
		{
			int dx = trie[x][i];
			int dy = trie[y][i];

			ans.mat[base][dfs(0, 0)] += cnt[dx] * cnt[dy];
		    ans.mat[base][dfs(dx, 0)] +=cnt[dy];
		    ans.mat[base][dfs(0, dy)] += cnt[dx];
		    ans.mat[base][dfs(dx, dy)] += 1;
		}
	}

	return base;
}

MAT operator * (const MAT &a, const MAT &b)
{
	MAT res;
	memset(res.mat, 0, sizeof(res.mat));

	for(int i = 1; i <= mcnt; i++)
        for(int k = 1; k <= mcnt; k++)
            for(int j = 1; j <= mcnt; j++)
                res.mat[i][j] = (res.mat[i][j] + (1ll * a.mat[i][k] * b.mat[k][j])) % mod;

	return res;
}

MAT pow(int p, MAT x)
{
	MAT res;
	for(int i = 1; i <= mcnt; i++) for(int j = 1; j <= mcnt; j++) res.mat[i][j] = (i == j);

	while(p)
	{
		if(p & 1) res = res * x;
		x = x * x; p >>= 1;
	}

	return res;
}

int main()
{
	FAST;

	memset(mp, -1, sizeof(mp));

	scanf("%d%d", &n, &m);

	for(int i = 1; i <= n; i++)
	{
		string s; cin >> s;
		cnt[add(s)]++;
	}

	dfs(0, 0);
	ans = pow(m, ans);
	printf("%d", ans.mat[1][1]);

    return 0;
}

#include<bits/stdc++.h>
#define N 251
#define mod 998244353
using namespace std;
typedef long long ll;
int n,m,tot=1,f[N][N],l,r,son[N*30][26],cnt,vis[N];
char str[N];
struct Node{int pos,x,y;}q[N*N];
inline int Mod(int x){return x>=mod?x-mod:x;}
inline int qpow(int a,int b){int res=1;while(b){if(b&1)res=1ll*res*a%mod;a=1ll*a*a%mod;b>>=1;}return res;}
struct Matrix{
	ll a[N][N];
	Matrix(){memset(a,0,sizeof a);}
	ll *operator [](int k){return a[k];}
	inline void Set(void){int i;for(i=1;i<=cnt;++i)a[i][i]=1;}
}ans;
inline Matrix operator*(Matrix a,Matrix b){
	int i,j,k;Matrix c;
	for(i=1;i<=cnt;++i)
		for(k=1;k<=cnt;++k)if(a[i][k]){
			for(j=1;j<=cnt;++j)c[i][j]+=a[i][k]*b[k][j];
			if((k%18)==0)for(j=1;j<=cnt;++j)c[i][j]%=mod;
		}
	for(i=1;i<=cnt;++i)for(j=1;j<=cnt;++j)c[i][j]%=mod;
	return c;
}
inline Matrix operator^(Matrix a,int k){
	Matrix res;res.Set();
	while(k){if(k&1)res=res*a;a=a*a;k>>=1;}
	return res;
}
inline int C(int&x){return !x?x=++tot:x;}
inline void Insert(void){
	int i,l=strlen(str+1),x=1;
	for(i=1;i<=l;++i)x=C(son[x][str[i]-'a']);
	vis[x]=1;
}
inline int F(int x,int y){if(x>y)swap(x,y);return !f[x][y]?(q[++r]={f[x][y]=++cnt,x,y},f[x][y]):f[x][y];}
signed main(void){
	int i,x,y,a,b;Node t;scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i)scanf("%s",str+1),Insert();
	l=1,r=0,F(1,1);
	while(l<=r){
		x=(t=q[l++]).x,y=t.y;
		for(i=0;i<26;++i)if((a=son[x][i])&&(b=son[y][i])){++ans[t.pos][F(a,b)];if(vis[a])++ans[t.pos][F(1,b)];;if(vis[b])++ans[t.pos][F(a,1)];;if(vis[a]&&vis[b])++ans[t.pos][F(1,1)];}
	}ans=ans^m;
	printf("%lld\n",ans[1][1]);
	return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <iomanip>
#define endl '\n'
#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double ldb;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef pair<LL, int> pli;
typedef pair<int, long> pil;
const int INF = 0x3f3f3f3f;
inline int read(){
    register int x; register char c(getchar()); register bool k;
    while((c < '0' || c > '9') && c ^ '-') if((c = getchar()) == EOF) exit(0);
    if(c ^ '-') x = c & 15, k = 1; else x = 0, k = 0;
    while(c = getchar(), c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c & 15);
    return k ? x : -x;
}

const int maxn = 100, mod = 998244353;
char s[10];
int trie[maxn][26], tot;
bool endp[maxn];

void insert(char *s){
    int len = strlen(s), cur = 0;
    for(int i = 0; i < len; i++){
        if(!trie[cur][s[i] - 'a']) trie[cur][s[i] - 'a'] = ++tot;
        cur = trie[cur][s[i] - 'a'];
    }
    endp[cur] = 1;
}

typedef vector<int> vec;
typedef vector<vec> mat;

// 计算矩阵A*矩阵B，元素对mod取模
mat mod_mul(mat &A, mat &B){
    mat C(A.size(), vec(B[0].size()));
    for(int i = 0; i < A.size(); i++){
        for(int k = 0; k < B.size(); k++){
            for(int j = 0; j < B[0].size(); j++){
                C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
            }
        }
    }
    return C;
}

// 计算矩阵A的n次方
mat mod_pow(mat A, LL n){
    mat B(A.size(), vec(A.size()));
    for(int i =0; i < A.size(); i++) B[i][i] = 1;
    while(n > 0){
        if(n & 1) B = mod_mul(B, A);
        A = mod_mul(A, A);
        n >>= 1;
    }
    return B;
}

queue<pii> que;
map<pii, int> mp;
int cnt;
int get_id(pii p){
    if(mp.count(p)) return mp[p];
    mp[p] = cnt++;
    que.push(p);
    return cnt - 1;
}

int main(){
    int n = read(), m = read();
    for(int i = 1; i <= n; i++){
        scanf("%s", s);
        insert(s);
    }
    mat M = mat(170, vec(170));
    get_id(pii(0, 0));
    while(que.size()){
        pii p = que.front(); que.pop();
        int p1 = p.first, p2 = p.second, id = get_id(p);
        for(int i = 0; i < 26; i++){
            int tp1 = trie[p1][i], tp2 = trie[p2][i];
            if(!tp1 || !tp2) continue;
            M[id][get_id(pii(tp1, tp2))]++;
            if(endp[tp1]) M[id][get_id(pii(0, tp2))]++;
            if(endp[tp2]) M[id][get_id(pii(0, tp1))]++;
            if(endp[tp1] && endp[tp2]) M[id][get_id(pii(0, 0))]++;
        }
    }
    /*for(int i = 0; i < 15; i++){
        for(int j = 0; j < 15; j++)
            cout << M[i][j] << ' ';
        cout << endl;
    }*/
    mat ans = mod_pow(M, m);
    cout << ans[0][0] << endl;
    return 0;
}

#include <iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#include<ctime>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<bitset>
#define sqr(x) ((x)*(x))
#define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
#define fd1(i,n) for ((i)=(n);(i)>=1;(i)--)
#define fz0g(i,n) for ((i)=0;(i)<=(n);(i)++)
#define fd0g(i,n) for ((i)=(n);(i)>=0;(i)--)
#define fz0k(i,n) for ((i)=0;(i)<(n);(i)++)
#define fd0k(i,n) for ((i)=(long long)((n)-1);(i)>=0;(i)--)
#define fz(i,x,y) for ((i)=(x);(i)<=(y);(i)++)
#define fd(i,y,x) for ((i)=(y);(i)>=(x);(i)--)
#define fzin fz1(i,n)
#define fzim fz1(i,m)
#define fzjn fz1(j,n)
#define fzjm fz1(j,m)
#define ff(c,itr) for (__typeof((c).begin()) itr=(c).begin();itr!=(c).end();++itr)
#define rdst(st,len){static char ss[len];scanf(" %s",ss);(st)=ss;}
#define incm(x,y) {x=((x)+(y))%mod;}
#define spln(i,n) (i==n?'\n':' ')
#define fac_init(n){fac[0]=fac[1]=inv[1]=fi[0]=fi[1]=1;fz(i,2,n){fac[i]=1ll*fac[i-1]*i%mod;inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;fi[i]=1ll*fi[i-1]*inv[i]%mod;}}
#define fi first
#define se second
#define mk make_pair
using namespace std;
inline void read(int &x)
{
	char c;int f=1;
	while(!isdigit(c=getchar()))if(c=='-')f=-1;
	x=(c&15);while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);
	x*=f;
}
const int mod=998244353;
const long long mod2=1ll*mod*mod;
int n,m,i,j,k,cnt=1,ch[45][26],ed[45];
int a[1005][1005],b[1005][1005];
long long c[1005][1005];
string st;
int id[45][45],cid;
void dfs(int x,int y)
{
	if(x>y){
		id[x][y]=id[y][x];
		return;
	}
	if(id[x][y]) return;
	id[x][y]=++cid;
	if(ed[x]) dfs(1,y);
	if(ed[y]) dfs(x,1);
	int i;
	fz0k(i,26)if(ch[x][i]&&ch[y][i])dfs(ch[x][i],ch[y][i]);
}
int main()
{
	cin>>n>>m;
	while(n--){
		cin>>st;
		int x=1;
		fz0k(i,st.size()){
			if(!ch[x][st[i]-'a']){
				ch[x][st[i]-'a']=++cnt;
			}
			x=ch[x][st[i]-'a'];
		}
		ed[x]++;
	}
	dfs(1,1);
	int x,y;
	fz1(x,cnt)fz1(y,cnt)if(id[x][y]){
		fz0k(i,26)if(ch[x][i]&&ch[y][i]){
			a[id[x][y]][id[ch[x][i]][ch[y][i]]]+=1;
			a[id[x][y]][id[ch[x][i]][1]]+=ed[ch[y][i]];
			a[id[x][y]][id[1][ch[y][i]]]+=ed[ch[x][i]];
			a[id[x][y]][id[1][1]]+=ed[ch[x][i]]*ed[ch[y][i]];
		}
	}
	cerr<<cid<<endl;
//	fz1(x,cnt)fz1(y,cnt)fz1(i,cnt)fz1(j,cnt)if(a[id[x][y]][id[i][j]]){
//		cerr<<x<<' '<<y<<' '<<i<<' '<<j<<' '<<a[id[x][y]][id[i][j]]<<endl;
//	}
	fz1(i,cid) b[i][i]=1;
	while(m){
		if(m&1){
			fz1(i,cid)fz1(j,cid){
				c[i][j]=0;
				fz1(k,cid){
					c[i][j]=(c[i][j]+1ll*a[i][k]*b[k][j]);
					if(c[i][j]>=mod2)c[i][j]-=mod2;
				}
			}
			fz1(i,cid)fz1(j,cid){
				b[i][j]=c[i][j]%mod;
			}
		}
		m/=2;
		fz1(i,cid)fz1(j,cid){
			c[i][j]=0;
			fz1(k,cid){
				c[i][j]=(c[i][j]+1ll*a[i][k]*a[k][j]);
				if(c[i][j]>=mod2)c[i][j]-=mod2;
			}
		}
		fz1(i,cid)fz1(j,cid){
			a[i][j]=c[i][j]%mod;
		}
	}
	cout<<b[id[1][1]][id[1][1]]<<endl;
	return 0;
}

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
// Problem: F. Chainword
// Contest: Codeforces - Educational Codeforces Round 107 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1511/problem/F
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define ll long long
#define pb push_back
#define f first
#define s second
#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL)
#define D(x) cerr << #x << " is " << (x) << "\n";
#define ld long double
#define li __int128

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>; ///find_by_order(),order_of_key()
template<int D, typename T>struct vec : public vector<vec<D - 1, T>> {template<typename... Args>vec(int n = 0, Args... args) : vector<vec<D - 1, T>>(n, vec<D - 1, T>(args...)) {}};
template<typename T>struct vec<1, T> : public vector<T> {vec(int n = 0, T val = T()) : vector<T>(n, val) {}};
template<class T1,class T2> ostream& operator<<(ostream& os, const pair<T1,T2>& a) { os << '{' << a.f << ", " << a.s << '}'; return os; }
template<class T> ostream& operator<<(ostream& os, const vector<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const deque<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T,greater<T> >& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T,greater<T> >& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> ostream& operator<<(ostream& os, const map<T1,T2>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> istream& operator>>(istream& is,pair<T1,T2>& a) {is>>a.f>>a.s;return is;}
template<class T> istream& operator>>(istream& is,vector<T>& a) {for(auto &p:a)is>>p;return is;}
int ri(){int x;scanf("%i",&x);return x;}
void rd(int&x){scanf("%i",&x);}
void rd(long long&x){scanf("%lld",&x);}
void rd(double&x){scanf("%lf",&x);}
void rd(long double&x){scanf("%Lf",&x);}
void rd(string&x){cin>>x;}
void rd(char*x){scanf("%s",x);}
template<typename T1,typename T2>void rd(pair<T1,T2>&x){rd(x.first);rd(x.second);}
template<typename T>void rd(vector<T>&x){for(T&p:x)rd(p);}
template<typename C,typename...T>void rd(C&a,T&...args){rd(a);rd(args...);}
//istream& operator>>(istream& is,__int128& a){string s;is>>s;a=0;int i=0;bool neg=false;if(s[0]=='-')neg=true,i++;for(;i<s.size();i++)a=a*10+s[i]-'0';if(neg)a*=-1;return is;}
//ostream& operator<<(ostream& os,__int128 a){bool neg=false;if(a<0)neg=true,a*=-1;ll high=(a/(__int128)1e18);ll low=(a-(__int128)1e18*high);string res;if(neg)res+='-';if(high>0){res+=to_string(high);string temp=to_string(low);res+=string(18-temp.size(),'0');res+=temp;}else res+=to_string(low);os<<res;return os;}

const int mod=998244353;
int add(int a,int b){
    a+=b;
    if(a>=mod)
        a-=mod;
    return a;
}
int sub(int a,int b){
    a-=b;
    if(a<0)
        a+=mod;
    return a;
}
int mul(int a,int b){
    return (long long)a*b%mod;
}
int pwrmod(int x,int k){
    int ans=1;
    for(;k;k>>=1,x=mul(x,x))
        if(k&1)
            ans=mul(ans,x);
    return ans;
}

const int N=41,L=26;
vector<int> nxt[N][L];
bool kr[N];
bool pref(string a,string b){
	if(a.size()<b.size())
		return pref(b,a);
	return a.substr(a.size()-b.size(),b.size())==b;
}
vector<vector<int>> mul(vector<vector<int>> &a,vector<vector<int>> &b){
	int n=a.size(),m=b[0].size(),l=a[0].size();
	assert(a[0].size()==b.size());
	vector<vector<int>> sol(n,vector<int>(m,0));
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			for(int k=0;k<l;k++)
				sol[i][j]=add(sol[i][j],mul(a[i][k],b[k][j]));
	return sol;
}
int main()
{
	int n=ri(),m=ri();
	vector<string> s(n);
	rd(s);
	map<string,int> done;
	int ind=0;
	vector<string> pre;

	done[""]=ind++;pre.pb("");

	for(int i=0;i<n;i++){
		string tr;
		for(int j=0;j<s[i].size();j++){
			tr+=s[i][j];
			if(done.find(tr)==done.end()){
				done[tr]=ind++;
				pre.pb(tr);
			}
			if(j==s[i].size()-1){
				kr[done[tr]]=1;
			}
		}
	}
	for(auto p:done){
		string tr=p.f;
		int i=p.s;
		for(int j=0;j<26;j++){
			char c='a'+j;
			string novi=tr+c,o;
			o+=c;
			if(done.find(novi)!=done.end())
				nxt[i][j].pb(done[novi]);
			if(kr[i]&&done.find(o)!=done.end())
				nxt[i][j].pb(done[o]);
		}
	}
	vector<pair<int,int>> pr;
	map<pair<int,int>,int> koji;
	for(int i=0;i<ind;i++)
		for(int j=0;j<ind;j++)
			if(pref(pre[i],pre[j])){
				pr.pb({i,j});
				koji[{i,j}]=pr.size()-1;
			}
	int L=pr.size();
	vector<vector<int>> mulMat(L,vector<int>(L,0));
	for(int k=0;k<L;k++){
		int i=pr[k].f,j=pr[k].s;
		for(int l=0;l<26;l++){
			for(auto p:nxt[i][l])
				for(auto d:nxt[j][l]){
					if(koji.find({p,d})!=koji.end()){
						int sl=koji[{p,d}];
						mulMat[k][sl]=add(mulMat[k][sl],1);
					}
				}
		}
	}
	printf("%i!\n",L);
	vector<vector<int>> begMat(1,vector<int>(L,0));
	begMat[0][0]=1;
	for(;m;m>>=1,mulMat=mul(mulMat,mulMat))
		if(m&1)
			begMat=mul(begMat,mulMat);
	int sol=0;
	for(int k=0;k<L;k++){
		int i=pr[k].f,j=pr[k].s;
		if(kr[i]&&kr[j])
			sol=add(sol,begMat[0][k]);
	}
	printf("%i\n",sol);
	return 0;
}

// Sometimes, the questions are complicated - and the answers are simple. //
#pragma GCC optimize ("O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
#pragma GCC optimize ("unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define ld  long double
#define IO ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int mod = 998244353;
const int N = 205;
int res[N][N];
void mul(int a[][N], int b[][N]) {

    memset(res, 0, sizeof res);
    for(int i = 0; i < N; i++)
        for(int k = 0; k < N; k++)
            if(res[i][k])
                for(int j = 0; j < N; j++)
                    res[i][j] = (1LL * a[i][k] * b[k][j] + res[i][j]) % mod;

    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++)
            a[i][j] = res[i][j];
}
void power(int temp[][N], int p) {

    int res[N][N] = {0};
    for(int i = 0; i < N; i++)
        res[i][i] = 1;

    while(p) {
        if(p & 1)
            mul(res, temp);
        mul(temp, temp);
        p >>= 1;
    }

    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++)
            temp[i][j] = res[i][j];
}
int n, m ;
int trie[50][30], node_ind;
bool final_state[50];
void insert(string & s) {
    int node = 0;
    for(auto i : s) {
        int cur = i - 'a';
        if(!trie[node][cur])
            trie[node][cur] = ++node_ind;
        node = trie[node][cur];
    }
    final_state[node] = true;
}
map<pair<int, int>, int >mop;
set<pair<int, int> > vis;
int get_ind(int x, int y) {
    if(mop.find({x, y}) == mop.end())
        mop[ {x, y}] = mop.size();
    return mop[ {x, y}];
}
void dfs(int node1, int node2, int mat[][N]) {

    if(vis.find({node1, node2}) != vis.end())
        return ;
    vis.insert({node1, node2});
    //cout<<node1<<" "<<node2<<"\n";
    for(int i = 0; i < 26; i++) {
        if(!trie[node1][i] || !trie[node2][i])continue;
        int x = trie[node1][i], y = trie[node2][i];

        mat[get_ind(node1, node2)][get_ind(x, y)] = 1;
        dfs(x, y, mat);

        if(final_state[x]) {
            mat[get_ind(node1, node2)][get_ind(0, y)] = 1;
            dfs(0, y, mat);
        }
        if(final_state[y]) {
            mat[get_ind(node1, node2)][get_ind(x, 0)] = 1;
            dfs(x, 0, mat);
        }
        if(final_state[x] && final_state[y]) {
            mat[get_ind(node1, node2)][get_ind(0, 0)]++;
        }
    }
}
int main() {
    IO
    int n, m;
    cin >> n >> m;
    while(n--) {
        string s;
        cin >> s;
        insert(s);
    }
    int cur[N][N] = {};
    get_ind(0, 0);
    dfs(0, 0, cur);

    power(cur, m);
    cout << cur[0][0];
}

#include <iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#include<ctime>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<bitset>
#define sqr(x) ((x)*(x))
#define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
#define fd1(i,n) for ((i)=(n);(i)>=1;(i)--)
#define fz0g(i,n) for ((i)=0;(i)<=(n);(i)++)
#define fd0g(i,n) for ((i)=(n);(i)>=0;(i)--)
#define fz0k(i,n) for ((i)=0;(i)<(n);(i)++)
#define fd0k(i,n) for ((i)=(long long)((n)-1);(i)>=0;(i)--)
#define fz(i,x,y) for ((i)=(x);(i)<=(y);(i)++)
#define fd(i,y,x) for ((i)=(y);(i)>=(x);(i)--)
#define fzin fz1(i,n)
#define fzim fz1(i,m)
#define fzjn fz1(j,n)
#define fzjm fz1(j,m)
#define ff(c,itr) for (__typeof((c).begin()) itr=(c).begin();itr!=(c).end();++itr)
#define rdst(st,len){static char ss[len];scanf(" %s",ss);(st)=ss;}
#define incm(x,y) {x=((x)+(y))%mod;}
#define spln(i,n) (i==n?'\n':' ')
#define fac_init(n){fac[0]=fac[1]=inv[1]=fi[0]=fi[1]=1;fz(i,2,n){fac[i]=1ll*fac[i-1]*i%mod;inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;fi[i]=1ll*fi[i-1]*inv[i]%mod;}}
#define fi first
#define se second
#define mk make_pair
using namespace std;
inline void read(int &x)
{
	char c;int f=1;
	while(!isdigit(c=getchar()))if(c=='-')f=-1;
	x=(c&15);while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);
	x*=f;
}
const int mod=998244353;
const long long mod2=1ll*mod*mod;
int n,m,i,j,k,cnt=1,ch[45][26],ed[45];
int a[1005][1005],b[1005][1005];
long long c[1005][1005];
string st;
int id[45][45],cid;
void dfs(int x,int y)
{
	if(x>y){
		return;
	}
	if(id[x][y]) return;
	id[x][y]=++cid;
	if(ed[x]) dfs(1,y);
	if(ed[y]) dfs(x,1);
	int i;
	fz0k(i,26)if(ch[x][i]&&ch[y][i])dfs(ch[x][i],ch[y][i]);
}
int main()
{
	cin>>n>>m;
	while(n--){
		cin>>st;
		int x=1;
		fz0k(i,st.size()){
			if(!ch[x][st[i]-'a']){
				ch[x][st[i]-'a']=++cnt;
			}
			x=ch[x][st[i]-'a'];
		}
		ed[x]++;
	}
	dfs(1,1);
	int x,y;
	fz1(x,cnt)fz1(y,cnt)if(x>y) id[x][y]=id[y][x];
	fz1(x,cnt)fz1(y,cnt)if(x<=y&&id[x][y]){
		fz0k(i,26)if(ch[x][i]&&ch[y][i]){
			a[id[x][y]][id[ch[x][i]][ch[y][i]]]+=1;
			a[id[x][y]][id[ch[x][i]][1]]+=ed[ch[y][i]];
			a[id[x][y]][id[1][ch[y][i]]]+=ed[ch[x][i]];
			a[id[x][y]][id[1][1]]+=ed[ch[x][i]]*ed[ch[y][i]];
		}
	}
	cerr<<cid<<endl;
//	fz1(x,cnt)fz1(y,cnt)fz1(i,cnt)fz1(j,cnt)if(a[id[x][y]][id[i][j]]){
//		cerr<<x<<' '<<y<<' '<<i<<' '<<j<<' '<<a[id[x][y]][id[i][j]]<<endl;
//	}
	fz1(i,cid) b[i][i]=1;
	while(m){
		if(m&1){
			fz1(i,cid)fz1(j,cid){
				c[i][j]=0;
				fz1(k,cid){
					c[i][j]=(c[i][j]+1ll*a[i][k]*b[k][j]);
					if(c[i][j]>=mod2)c[i][j]-=mod2;
				}
			}
			fz1(i,cid)fz1(j,cid){
				b[i][j]=c[i][j]%mod;
			}
		}
		m/=2;
		fz1(i,cid)fz1(j,cid){
			c[i][j]=0;
			fz1(k,cid){
				c[i][j]=(c[i][j]+1ll*a[i][k]*a[k][j]);
				if(c[i][j]>=mod2)c[i][j]-=mod2;
			}
		}
		fz1(i,cid)fz1(j,cid){
			a[i][j]=c[i][j]%mod;
		}
	}
	cout<<b[id[1][1]][id[1][1]]<<endl;
	return 0;
}

#include <bits/stdc++.h>

#define F first
#define S second

using namespace std;
using ll = long long;
using pi = pair<int, int>;
using vi = vector<int>;
using vpi = vector<pi>;

template<class T> bool ckmin(T& a, T b) { return b < a ? a = b, true : false; }
template<class T> bool ckmax(T& a, T b) { return a < b ? a = b, true : false; }

const int MOD = 998244353;

struct Matrix {
    int n;
    vector<vector<int>> w;

    Matrix(const int n) : n(n), w(n, vector<int>(n)) { }

    Matrix operator * (const Matrix& m) const {
        Matrix res(n);

        for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j) {
            if (!w[i][j]) continue;
            for (int t = 0; t < n; ++t) {
                res.w[i][t] = (res.w[i][t] + (ll) w[i][j] * m.w[j][t]) % MOD;
            }
        }

        return res;
    }
};

void dfs_forw(int v, const int r, const vector<vector<int>>& w, vector<char>& used) {
    if (used[v]) return;
    used[v] = true;

    for (int i = 0; i < r; ++i) {
        if (w[v][i]) dfs_forw(i, r, w, used);
    }
}

void dfs_back(int v, const int r, const vector<vector<int>>& w, vector<char>& used) {
    if (used[v]) return;
    used[v] = true;

    for (int i = 0; i < r; ++i) {
        if (w[i][v]) dfs_forw(i, r, w, used);
    }
}

void solve() {
    int n, m; cin >> n >> m;

    map<string, int> id;
    id[""] = 0;
    int vc = 1;

    vector<string> v(n), phi { "" };
    for (string& s : v) {
        cin >> s;
        for (int i = 1; i <= size(s); ++i) {
            auto t = s.substr(0, i);
            if (!id.count(t)) {
                id[t] = vc++;
                phi.push_back(t);
            }
        }
    }

    const int k = size(id);
    const int r = k * k;
    vector w(r, vector<int>(r));

    for (int ia = 0; ia < k; ++ia)
    for (int ib = 0; ib < k; ++ib) {
        for (char ch = 'a'; ch <= 'z'; ch++) {
            auto ta = phi[ia] + ch; const int sa = id.count(ta) ? id[ta] : -1;
            auto tb = phi[ib] + ch; const int sb = id.count(tb) ? id[tb] : -1;

            for (int ja = 0; ja < n; ++ja) {
                if (ta != v[ja]) continue;
                for (int jb = 0; jb < n; ++jb) {
                    if (tb != v[jb]) continue;
                    w[ia*k+ib][0]++;
                }

                if (sb != -1) w[ia*k+ib][sb]++;
            }

            for (int jb = 0; jb < n; ++jb) {
                if (sa != -1 && tb == v[jb]) w[ia*k+ib][sa*k]++;
            }

            if (sa != -1 && sb != -1) w[ia*k+ib][sa*k+sb]++;
        }
    }

    vector<char> u1(r), u2(r);
    int us = 0;

    dfs_forw(0, r, w, u1);
    dfs_back(0, r, w, u2);

    vector<int> tid;

    for (int i = 0; i < r; ++i) {
        if (u1[i] && u2[i]) {
            tid.push_back(i);
        }
    }

    const int p = size(tid);

    Matrix ans(p), mul(p);

    for (int i = 0; i < p; ++i)
    for (int j = 0; j < p; ++j) {
        mul.w[i][j] = w[tid[i]][tid[j]];
    }

    for (int i = 0; i < p; ++i) ans.w[i][i] = 1;

    for (; m != 0; m >>= 1) {
        if (m & 1) ans = ans * mul;
        mul = mul * mul;
    }

    cout << ans.w[0][0] << '\n';
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    int t = 1;
    // cin >> t;
    while (t--) solve();
}

// dp[0] = 1
// dp[1] = 1
// dp[2] = 2
// dp[3] = 3
// dp[4] = 5

#include<bits/stdc++.h>
using namespace std;

#define mp make_pair
#define mt make_tuple
#define rep(i,begin,end) for (__typeof(begin) i=(begin),_end=(end),_step=1-2*((begin)>(end));i!=_end;i+=_step)

// OUTPUT
template<class a, class b>
ostream& operator << (ostream& os, const pair<a,b>& p)  {
    os<<"("<<p.first<<","<<p.second<<")";
    return os;
}
template<class T>
ostream& operator << (ostream& os, const vector<T>& v)  {
    os<<"[";
    if (!v.size())
        os<<"]";
    else
        for (int i=0;i<v.size();++i)
            os<<v[i]<<",]"[i==v.size()-1];
    return os;
}
template<class T>
ostream& operator << (ostream& os, const set<T>& s)  {
    os<<"{";
    if (!s.size())
        os<<"}";
    else
        for (auto x:s)
            os<<x<<",}"[x==*s.rbegin()];
    return os;
}

void printr(ostream& os){os<<'\n';}
template<class T, class... Args>
void printr(ostream& os, const T& t, const Args&... args){
    os<<t; if (sizeof...(args)) os<<" ";
    printr(os,args...);
}
#define print(args...) printr(cout,##args)

// INPUT
template<class T>
void read(T& x) {cin>>x;}
template<class T, class... Args>
void read(T& t, Args&... args){
    read(t),read(args...);
}
template<class T>
void readarray(T* A,int n)  {
    rep(i,0,n) read(A[i]);
}

// DEBUG
void dbgr(ostream& os) { os<<endl; }
template<class T, class... Args>
void dbgr(ostream& os, const T& t, const Args&... args) {
    os<<t; if (sizeof...(args)) os<<", ";
    dbgr(os,args...);
}
#define dbg(args...) cout<<#args<<" = ", dbgr(cout,##args) //cout can be changed

#define maxn 500050
#define modu 998244353
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

// COMMON FUNCTION
// min
template<class T>
T min(const vector<T>& v) { return *min_element(v.begin(),v.end()); }
// max
template<class T>
T max(const vector<T>& v) { return *max_element(v.begin(),v.end()); }

LL pw(LL a,LL k=modu-2) {
    LL ans=1;
    for (a%=modu;k;k>>=1)   {
        if (k&1)
            ans=ans*a%modu;
        a=a*a%modu;
    }
    return ans;
}

struct Matrix   {
    static const int N=300;
    LL a[N][N];
    Matrix(int x=0)   {
        memset(a,0,sizeof(a));
        for (int i=0;i<N;++i)
            a[i][i]=x;
    }
    LL* operator [] (int x)    {
        return a[x];
    }

    friend Matrix operator * (Matrix a,Matrix b)    {
        Matrix c;
        rep(i,0,N)
            rep(k,0,N)
                rep(j,0,N)
                    c[i][j]=(c[i][j]+a[i][k]*b[k][j])%modu;
        return c;
    }
    friend ostream& operator << (ostream& os,Matrix b)    {
        rep(i,0,N)  {
            rep(j,0,N)
                cout<<b[i][j]<<" ";
            cout<<endl;
        }
        return os;
    }
};

int n,m;
string s[maxn],ms[maxn];

int main()  {
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);

    int n,m;
    read(n,m);
    readarray(s,n);

    int tot=1;
    map<string,int> suf;
    rep(i,0,n)
        rep(len,1,s[i].size()+1)  {
            string t=s[i].substr(0,len+1);
            if (!suf.count(t))  {
                // cout<<tot<<":"<<t<<endl;
                ms[tot]=t;
                suf[t]=tot++;
            }
        }

    Matrix trans(0),res(1);
    // dbg(tot);
    rep(i,1,6)
        rep(j,0,tot)
            trans[i*tot+j][(i-1)*tot+j]=1;
    auto join=[&](int i,int j,int len,int d=1)  {
        // cout<<ms[i]<<" -> "<<ms[j]<<" ~ "<<len<<endl;
        trans[j][(len-1)*tot+i]+=d;
    };

    rep(i,0,n) join(0,0,s[i].size()),join(0,suf[s[i]],s[i].size());
    rep(i,0,n)
        rep(j,0,n)  {
            if (s[j].size()>=s[i].size()) continue;
            if (s[i].substr(s[i].size()-s[j].size())==s[j])  {
                auto t=s[i].substr(0,s[i].size()-s[j].size());
                if (suf.count(t))
                    join(suf[t],0,s[j].size(),2);
            }
        }
    for (auto p:suf)
        rep(i,0,n)  {
            auto t=p.first+s[i];
            if (t.size()<=5&&suf.count(t))  {
                join(p.second,suf[t],s[i].size());
            }

            if (s[i].size()<=p.first.size()) continue;
            if (s[i].substr(0,p.first.size())==p.first) {
                auto t=s[i].substr(p.first.size());
                if (suf.count(t))
                    join(p.second,suf[t],t.size());
            }
        }

    // rep(i,0,tot)
    //     rep(j,0,6*tot)
    //         if (trans[i][j])
    //             cout<<"("<<j/tot<<","<<ms[j%tot]<<") -> ("<<i/tot<<","<<ms[i%tot]<<")"<<endl;

    // rep(t,1,m+1)    {
    //     res=res*trans;
    //     rep(i,0,tot)
    //         if (res[i][0])
    //             cout<<"dp["<<t<<"]["<<ms[i%tot]<<"]="<<res[i][0]<<endl;
    //     cout<<endl;
    // }
    for (;m;m>>=1)  {
        if (m&1)
            res=res*trans;
        trans=trans*trans;
    }
    print(res[0][0]);
    return 0;
}
/*README
1. Is modu correct?
2. Is maxn correct?
*/

#include <bits/stdc++.h>

using namespace std;

#ifdef Adrian
#include "debug.h"
#else
#define debug(...) 9999
#endif

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef complex<ll> point;
#define F first
#define S second
#define ii pair<int, int>

ll mod = 998244353;
vector<vector<ll>> mul(vector<vector<ll>> a, vector<vector<ll>> b)
{
    int n = a.size();
    vector<vector<ll>> c(n, vector<ll>(n));
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
            for(int k=0; k<n; k++)
                c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % mod;
    return c;
}
vector<vector<ll>> pot(vector<vector<ll>> a, int b)
{
    int n = a.size();
    vector<vector<ll>> c(n, vector<ll>(n));
    for(int i=0; i<n; i++) c[i][i] = 1;
    for(; b>0; b>>=1)
    {
        if(b & 1) c = mul(c, a);
        a = mul(a, a);
    }
    return c;
}

int main()
{
#ifdef Adrian
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
#else
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif

    int n, m;
    cin>>n>>m;

    vector<string> v(n);
    for(auto &i:v) cin>>i;
    sort(v.begin(), v.end(), [](string &x, string &y)
    { return x.size() > y.size(); });

    vector<vector<int>> f(n);
    vector<bool> fin = {false};
    vector<vector<int>> ch;
    ch.push_back(vector<int>(26, -1));

    for(int i=0; i<n; i++)
    {
        int r = 0;
        for(auto &j:v[i])
        {
            int c = j - 'a';
            if(ch[r][c] == -1)
            {
                ch.push_back(vector<int>(26, -1));
                ch[r][c] = fin.size();
                fin.push_back(false);
            }

            r = ch[r][c];
            f[i].push_back(r);
        }
        fin[r] = true;
    }

    int p = 0;
    int sz = ch.size();
    vector<vector<int>> valid(sz,
            vector<int>(sz, -1));
    valid[0][0] = p++;
    for(int i=0; i<n; i++)
        for(int j=i; j<n; j++)
            for(int ti=0; ti<v[i].size(); ti++)
                for(int tj=0; tj<v[j].size(); tj++)
                {
                    int a = f[i][ti], b = f[j][tj];
                    if(valid[a][b] != -1) continue;
                    bool ok = true;
                    for(int k=0; k<=min(ti, tj); k++)
                        ok |= (v[i][ti-k] == v[j][tj-k]);
                    if(ok) valid[a][b] = p++;
                }
    for(int i=1; i<sz; i++)
    {
        valid[0][i] = p++;
        valid[i][0] = p++;
    }

    vector<vector<ll>> mat(p,
            vector<ll>(p));
    for(int i=0; i<sz; i++)
        for(int j=0; j<sz; j++)
        {
            if(valid[i][j] == -1) continue;
            int x = valid[i][j];
            for(int k=0; k<26; k++)
            {
                int a = ch[i][k], b = ch[j][k];
                if(a != -1 && b != -1)
                {
                    if(valid[a][b] != -1) ++mat[x][valid[a][b]];
                    if(fin[a]) ++mat[x][valid[0][b]];
                    if(fin[b]) ++mat[x][valid[a][0]];
                    if(fin[a] && fin[b]) ++mat[x][0];
                }
            }
        }

    auto ans = pot(mat, m);
    cout<<ans[0][0]<<'\n';

    return 0;
}

/*
3 5
ababa
ab
a

2 4
ab
cd

5 100
a
aa
aaa
aaaa
aaaaa

8 3
ba
bbb
bb
aba
aab
baa
b
a

 */

// nauynix
// 13/04/2021
#include <bits/stdc++.h>
using namespace std;
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define fi first
#define se second
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<PII> VII;
typedef vector<VI> VVI;
typedef long long int  ll;
const int INF = 1e9 + 7;
const int mod = 998244353;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int nxt() {int x;cin >> x;return x;}

const int AL = 26;

void norm(int &a) {
    a %= mod;
    if (a < 0) a += mod;
}

struct node {
    int nxt[AL];
    bool term;
    char ch;
    node() {
        memset(nxt, -1, sizeof(nxt));
        term = false;
    }
    int& operator [](const int x) {
        return nxt[x];
    }
};

vector<node> trie;

void add(const string &s){
    int cur = 0;
    for (const char &c : s){
        if (trie[cur][c - 'a'] == -1){
            trie[cur][c - 'a'] = trie.size();
            trie.push_back(node());
        }
        cur = trie[cur][c - 'a'];
        trie[cur].ch = c;
    }
    trie[cur].term = true;
}

map<PII, int> conv;
int s = 161;
struct Matrix {
    VVI a = VVI(s, VI(s));
    Matrix operator *(const Matrix& other) {
        Matrix product;
        rep (i, 0, s) rep (j, 0, s) rep (k, 0, s) {
            product.a[i][k] = (product.a[i][k] + (long long) a[i][j] * other.a[j][k]) % mod;
        }
        return product;
    }
};

Matrix expo_power(Matrix a, long long k) {
    Matrix product;
    rep (i, 0, s) product.a[i][i] = 1;
    while(k > 0) {
        if(k % 2) {
            product = product * a;
        }
        a = a * a;
        k /= 2;
    }
    return product;
}

void dfs(int u, VI a) {
    a.pb(u);
    for (int x : a) if (trie[u].ch == trie[x].ch) conv[{u, x}] = conv.size();
    for (int i = 0; i < 26; i++) {
        if (trie[u][i] != -1) {
            dfs(trie[u][i], a);
        }
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n = nxt(), m = nxt();
    VS a(n);
    rep (i, 0, n) cin >> a[i];
    trie.assign(1, node());
    rep (i, 0, n) {
        add(a[i]);
    }
    dfs(0, VI());
    s = conv.size();
    Matrix b;
    rep (i, 0, trie.size()) {
        rep (j, 0, i+1) {
            if (conv.count({i, j}) == 0) continue;
            rep (ch, 0, 26) {
                rep (reseti, 0, 2) {
                    rep (resetj, 0, 2) {
                        if (reseti && !trie[i].term) continue;
                        if (resetj && !trie[j].term) continue;
                        int ti = i, tj = j;
                        if (reseti) ti = 0;
                        if (resetj) tj = 0;
                        int k = trie[ti][ch];
                        int l = trie[tj][ch];
                        if (k < l) swap(k, l);
                        /* if (i == 2 && j == 1 && k == 3 && l == 2) printf("HI\n"); */
                        if (conv.count({k, l}) == 0) continue;
                        b.a[conv[{k, l}]][conv[{i, j}]] += 1;
                        /* printf("%d %d -> %d %d\n", i, j, k, l); */
                    }
                }
            }
        }
    }
    Matrix ans = expo_power(b, m);
    ll sum = 0;
    rep (i, 0, trie.size()) {
        rep (j, 0, i+1) {
            if(trie[i].term && trie[j].term) {
                sum += ans.a[conv[{i, j}]][0];
                sum %= mod;
            }
        }
    }
    printf("%lld\n", sum);
    return 0;
}

#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
#define ll long long
#define PII pair<int,int>
const ll N=50 , INF=1e9 , mod=998244353 , Z=166;

struct Matrix
{	ll M[Z][Z];

	ll* operator[](int i) {	  return M[i];	}

	Matrix operator *(const Matrix &B)
	{	static Matrix T1;
		memset(T1.M,0,sizeof T1.M);
		for(int i=0;i<Z;i++)
		for(int j=0;j<Z;j++)
		for(int k=0;k<Z;k++)
		T1[i][j]+=M[i][k]*B.M[k][j],T1[i][j]%=mod;
		return T1;
	}

};
	Matrix fmi(Matrix& G, ll pow)
	{
		static Matrix T2;
		memset(T2.M,0,sizeof T2.M);
		for(int i=0;i<Z;i++) T2[i][i]=1;

		while(pow)
		{	if(pow&1) T2=T2*G;
			G=G*G;
			pow>>=1;
		}
		return T2;
	}

Matrix M0,M1,res;

struct Trie
{
	int ch[N][26];
	bool ed[N];
	int idx=0;

	void insert(char s[])
	{	int p=0;
		for(int i=0;s[i];i++)
		{	int c=s[i]-'a';
			if(!ch[p][c]) ch[p][c]=++idx;
			p=ch[p][c];
		}
		ed[p]=1;
	}

	int mp[3000],idn;
	bool ED[3000];

	int dfs(int u,int v)
	{	if(mp[u*N+v]) return mp[u*N+v];

		mp[u*N+v]=++idn;
		ED[idn]=(ed[u]&&ed[v]);
		int x=idn , su , sv ;

		for(int i=0;i<26;i++)
		{
			if(ch[u][i])
			{
				if(ch[v][i])
				{	su=ch[u][i] , sv=ch[v][i];
					M1[x][dfs(su,sv)]++;
				}
				if(ed[v]&&ch[0][i])
				{	su=ch[u][i] , sv=ch[0][i];
					M1[x][dfs(su,sv)]++;
				}
			}

			if(ed[u]&&ch[0][i])
			{	if(ch[v][i])
				{	su=ch[0][i] , sv=ch[v][i];
					M1[x][dfs(su,sv)]++;
				}
				if(ed[v]&&ch[0][i])
				{	su=ch[0][i] , sv=ch[0][i];
					M1[x][dfs(su,sv)]++;
				}
			}
		}
		return mp[u*N+v];
	}

	void solve(int m)
	{	idn=0;
		memset(mp,0,sizeof mp);
		memset(ED,0,sizeof ED);

		for(int c=0;c<26;c++) if(ch[0][c]) dfs(ch[0][c],ch[0][c]);

		for(int c=0;c<26;c++) if(ch[0][c]) M0[0][mp[ch[0][c]*N+ch[0][c]]]++;
		res=M0*fmi(M1,m-1);
		ll ans=0;
		for(int i=1;i<=idn;i++) if(ED[i]) ans=(ans+res[0][i])%mod;
		printf("%lld",ans);
	}

}trie;

char s[10];
signed main()
{	int n,m;scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%s",s),trie.insert(s);
	trie.solve(m);
    return 0;
}

#include <bits/stdc++.h>

#define fi first
#define se second
#define DB double
#define U unsigned
#define P std::pair
#define LL long long
#define LD long double
#define pb emplace_back
#define MP std::make_pair
#define SZ(x) ((int)x.size())
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 8 + 5;
const int MAXM = 168 + 5;
const int ha = 998244353;

inline void add(int &x,int y){
    x += y-ha;x += x>>31&ha;
}

int N;
struct Matrix{
    int a[MAXM][MAXM];
    Matrix(){CLR(a,0);}
    inline int* operator [] (const int &n){return a[n];}
    inline const int* operator [] (const int &n) const {return a[n];}

    Matrix operator * (const Matrix &t) const {
        Matrix res;
        FOR(i,0,N-1) FOR(j,0,N-1) FOR(k,0,N-1) add(res.a[i][j],1ll*a[i][k]*t.a[k][j]%ha);
        return res;
    }
}A;

Matrix qpow(Matrix a,int n){
    Matrix res;FOR(i,0,N-1) res.a[i][i] = 1;
    while(n){
        if(n&1) res = res*a;
        a = a*a;
        n >>= 1;
    }
    return res;
}

int n,m;
int ch[MAXN][26],tot=1;
int id[MAXN][MAXN];
char str[MAXN];
bool vis[MAXN];

inline void insert(char str[]){
    int len = strlen(str+1),v = 1;
    FOR(i,1,len){
        int o = str[i]-'a';
        if(!ch[v][o]) ch[v][o] = ++tot;
        v = ch[v][o];
    }
    vis[v] = 1;
}

inline void upd(int x,int y){// x -> y
    add(A[y][x],1);
}

inline int gao(int x,int y){
    if(x > y) std::swap(x,y);
    if(id[x][y] != -1) return id[x][y];
    id[x][y] = N++;int v = id[x][y];
    FOR(i,0,25){
        if(ch[x][i] && ch[y][i]){
            int xx = ch[x][i],yy = ch[y][i];
            upd(v,gao(xx,yy));
            if(vis[xx]) upd(v,gao(1,yy));
            if(vis[yy]) upd(v,gao(xx,1));
            if(vis[xx] && vis[yy]) upd(v,gao(1,1));
        }
    }
    return v;
}

int main(){
    scanf("%d%d",&n,&m);
    CLR(id,-1);
    FOR(i,1,n){
        scanf("%s",str+1);
        insert(str);
    }
    gao(1,1);
    A = qpow(A,m);
    printf("%d\n",A[0][0]);
    return 0;
}

#include <bits/stdc++.h>

using namespace std;
typedef long long Int;
const int N = 50;
const int p = 998244353;

int cnt;
int fa[N];
int val[N];
int is_end[N];
int ch[N][26];

struct Matrix {
    int n, m;
    vector<vector<Int>> vec;

    Matrix(int n, int m) : n{n}, m{m}, vec(n, vector<Int>(m)) {}
};

Matrix operator*(Matrix &x, Matrix &y) {
    Matrix z(x.n, y.m);
    for (int i = 0; i < x.n; ++i)
        for (int j = 0; j < x.m; ++j)
            for (int k = 0; k < y.m; ++k)
                z.vec[i][k] += x.vec[i][j] * y.vec[j][k] % p;
    for (int i = 0; i < z.n; ++i)
        for (int j = 0; j < z.m; ++j)
            z.vec[i][j] %= p;
    return z;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    bool tag = 0;
    for (int i = 0; i < n; ++i) {
        char s[6];
        cin >> s;
        int x = 0;
        for (int j = 0; s[j]; ++j) {
            int c = s[j] - 'a';
            if (!ch[x][c]) {
                ch[x][c] = ++cnt;
                fa[cnt] = x;
                val[cnt] = c;
            }
            x = ch[x][c];
        }
        is_end[x] = 1;
        tag = strcmp(s, "abdd") == 0;
    }
    vector<pair<int, int>> vec;
    for (int i = 1; i <= cnt; i++)
        for (int j = 1; j <= cnt; j++) {
            for (int x = i, y = j; x; x = fa[x], y = fa[y])
                if (val[x] != val[y] && !y) goto loop;
            vec.emplace_back(i, j);
            loop:;
        }
    n = (int) vec.size();
    if (tag) {
        cout << n << endl;
        return 0;
    }
    Matrix X(n, n);
    for (int i = 0; i < n; ++i) {
        int x = vec[i].first;
        int y = vec[i].second;
        for (int c = 0; c < 26; ++c) {
            if (ch[x][c] && ch[y][c])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[x][c], ch[y][c])) - vec.begin()] = 1;
            if (ch[0][c] && ch[y][c] && is_end[x])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[0][c], ch[y][c])) - vec.begin()] = 1;
            if (ch[x][c] && ch[0][c] && is_end[y])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[0][c], ch[x][c])) - vec.begin()] = 1;
            if (ch[0][c] && is_end[x] && is_end[y])
                X.vec[i][lower_bound(vec.begin(), vec.end(), pair(ch[0][c], ch[0][c])) - vec.begin()] = x == y ? 1 : 2;
        }
    }
    Matrix A(n, n);
    for (int i = 0; i < n; ++i) A.vec[i][i] = 1;
    for (; m; m >>= 1) {
        if (m & 1)
            A = X * A;
        X = X * X;
    }
    Int ans = 0;
    for (int i = 0; i < n; ++i) {
        int x = vec[i].first;
        int y = vec[i].second;
        if (is_end[x] && is_end[y])
            ans += A.vec[n - 1][i] * (x == y ? 1 : 2);
    }
    cout << ans % p << endl;
    return 0;
}

#include<bits/stdc++.h>
#define mk make_pair
using namespace std;
const int N=233;
const int p=998244353;

int read()
{
	int s=0;
	char c=getchar(),lc='+';
	while (c<'0'||'9'<c) lc=c,c=getchar();
	while ('0'<=c&&c<='9') s=s*10+c-'0',c=getchar();
	return lc=='-'?-s:s;
}
void write(int x)
{
	if (x<0) putchar('-'),x=-x;
	if (x<10) putchar(x+'0');
	else write(x/10),putchar(x%10+'0');
}
void print(int x=-1,char c='\n')
{
	write(x);
	putchar(c);
}
void add(int &x,int y){x+=y;if (x>=p) x-=p;}
int cnt,id[50][50],vis[50][50];
struct Matrix{int a[N][N];}tr;
struct Vector{int a[N];}f;
Matrix operator *(const Matrix &a,const Matrix &b)
{
	Matrix ret;
	memset(ret.a,0,sizeof(ret.a));
	for (int i=1;i<=cnt;i++)
	for (int k=1;k<=cnt;k++)
	for (int j=1;j<=cnt;j++)
	add(ret.a[i][j],1LL*a.a[i][k]*b.a[k][j]%p);
	return ret;
}
Vector operator *(const Vector &a,const Matrix &b)
{
	Vector ret;
	memset(ret.a,0,sizeof(ret.a));
	for (int i=1;i<=cnt;i++)
	for (int j=1;j<=cnt;j++)
	add(ret.a[j],1LL*a.a[i]*b.a[i][j]%p);
	return ret;
}
char a[10];
struct trie
{
	int cnt;
	struct node
	{
		int son[26],end,down;
	}t[50];
	void insert(char *a,int len)
	{
		int now=0;
		#define to t[now].son[a[i]-'a']
		for (int i=1;i<=len;i++)
		{
			if (!to) to=++cnt;
			now=to;
		}
		t[now].end=1;
		#undef to
	}
	void ysgs()
	{
		for (int i=0;i<=cnt;i++)
		for (int j=0;j<26;j++) t[i].down|=!!t[i].son[j];
	}
	void dfs(int u,int v)
	{
		if (vis[u][v]) return;
		vis[u][v]=1;
		for (int k=0;k<26;k++)
		if (t[u].son[k]&&t[v].son[k])
		{
			int nu=t[u].son[k],nv=t[v].son[k];
			for (int i=!t[nu].down;i<=t[nu].end;i++)
			for (int j=!t[nv].down;j<=t[nv].end;j++)
			{
				nu=t[u].son[k],nv=t[v].son[k];
				if (i) nu=0; if (j) nv=0;
				dfs(nu,nv);
			}
		}
	}
	void build()
	{
		for (int u=0;u<=cnt;u++)
		for (int v=u;v<=cnt;v++)
		if (id[u][v])
		for (int k=0;k<26;k++)
		if (t[u].son[k]&&t[v].son[k])
		{
			int nu=t[u].son[k],nv=t[v].son[k];
			for (int i=!t[nu].down;i<=t[nu].end;i++)
			for (int j=!t[nv].down;j<=t[nv].end;j++)
			{
				nu=t[u].son[k],nv=t[v].son[k];
				if (i) nu=0; if (j) nv=0;
				tr.a[id[u][v]][id[nu][nv]]=1+(!nu&&!nv&&u!=v);
//				print(id[u][v],' ');
//				print(id[nu][nv],':');
//				print(tr.a[id[u][v]][id[nu][nv]]);
			}
		}
	}
}t;

signed main(signed Goodbye,char *Wangang[])
{
	(void)Goodbye,(void)Wangang;
	int n=read(),m=read();
	for (int i=1;i<=n;i++)
	{
		scanf("%s",a+1);
		t.insert(a,strlen(a+1));
	}
	t.ysgs();
	t.dfs(0,0);
	for (int i=0;i<=t.cnt;i++)
	for (int j=i;j<=t.cnt;j++)
	if (vis[i][j]) id[i][j]=id[j][i]=++cnt;
	t.build();
	f.a[1]=1;
	while (m)
	{
		if (m&1) f=f*tr;
		tr=tr*tr;
		m/=2;
	}
	print(f.a[1]);

	return 0;
}

#include<bits/stdc++.h>
using namespace std;
#ifdef local
void debug_out() { cerr << endl; }
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
    cerr << " " << to_string(H);
    debug_out(T...);
}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
typedef long long ll;
#define f(i, l, r) for(int i=l;i<=r;i++)
#define rf(i, r, l) for(int i=r;i>=l;--i)
#define all(x) x.begin(),x.end()
const int N = 2e5+10, mod = 998244353;
ll power(ll a, ll b) {ll res = 1;while (b) {if (b & 1)res = res * a % mod;a = a * a % mod;b >>= 1;}return res;}
ll INV(ll a){return power(a,mod-2);}
mt19937 Rand(123456);
int Range(int l,int r){
    return l+Rand()%(r-l+1);
}

namespace linear_seq {
#define rep(i,a,n) for (int i=a;i<n;i++)
#define VI vector<int>
#define SZ(x) ((int)(x).size())
#define pb push_back
    const int N = 10010;
    ll res[N], base[N], _c[N], _md[N];
    vector<ll> Md;
    void mul(ll* a, ll* b, int k)
    {
        rep(i, 0, k + k) _c[i] = 0;
        rep(i, 0, k) if (a[i]) rep(j, 0, k) _c[i + j] = (_c[i + j] + a[i] * b[j]) % mod;
        for (int i = k + k - 1; i >= k; i--) if (_c[i])
                rep(j, 0, SZ(Md)) _c[i - k + Md[j]] = (_c[i - k + Md[j]] - _c[i] * _md[Md[j]]) % mod;
        rep(i, 0, k) a[i] = _c[i];
    }
    int solve(ll n, VI a, VI b)
    {
        ll ans = 0, pnt = 0;
        int k = SZ(a);
        assert(SZ(a) == SZ(b));
        rep(i, 0, k) _md[k - 1 - i] = -a[i]; _md[k] = 1;
        Md.clear();
        rep(i, 0, k) if (_md[i] != 0) Md.push_back(i);
        rep(i, 0, k) res[i] = base[i] = 0;
        res[0] = 1;
        while ((1ll << pnt) <= n) pnt++;
        for (int p = pnt; p >= 0; p--)
        {
            mul(res, res, k);
            if ((n >> p) & 1)
            {
                for (int i = k - 1; i >= 0; i--) res[i + 1] = res[i]; res[0] = 0;
                rep(j, 0, SZ(Md)) res[Md[j]] = (res[Md[j]] - res[k] * _md[Md[j]]) % mod;
            }
        }
        rep(i, 0, k) ans = (ans + res[i] * b[i]) % mod;
        if (ans < 0) ans += mod;
        return ans;
    }
    VI BM(VI s) {
        VI C(1, 1), B(1, 1);
        int L = 0, m = 1, b = 1;
        rep(n, 0, SZ(s)) {
            ll d = 0;
            rep(i, 0, L + 1) d = (d + (ll)C[i] * s[n - i]) % mod;
            if (d == 0) ++m;
            else if (2 * L <= n) {
                VI T = C;
                ll c = mod - d * power(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                L = n + 1 - L; B = T; b = d; m = 1;
            }
            else {
                ll c = mod - d * power(b, mod - 2) % mod;
                while (SZ(C) < SZ(B) + m) C.pb(0);
                rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
                ++m;
            }
        }
        return C;
    }
    int gao(VI a, ll n) {
        VI c = BM(a);
        c.erase(c.begin());
        debug(c.size());
        rep(i, 0, SZ(c)) c[i] = (mod - c[i]) % mod;
        return solve(n, c, VI(a.begin(), a.begin() + SZ(c)));
    }
};
int dp[300][1700];
int mat[1700][1700];
struct Trie {
    int tr[N][26], tot;
    bool key[N];
    void insert(char* s) {
        int u = 0;
        for (int i = 1; s[i];i++) {
            int c = s[i] - 'a';
            if (tr[u][c] == 0)tr[u][c] = ++tot;
            u = tr[u][c];
        }
        key[u]=1;
    }
    int id(int x,int y){
        return y+x*(tot+1);
    }
    void build_mat(int m){
        f(u,0,tot)f(v,0,tot)f(w,0,25){
            if(tr[u][w]&&tr[v][w])mat[id(u,v)][id(tr[u][w],tr[v][w])]=1;
            if(tr[0][w]&&tr[v][w]&&key[u])mat[id(u,v)][id(tr[0][w],tr[v][w])]=1;
            if(tr[0][w]&&tr[u][w]&&key[v])mat[id(u,v)][id(tr[u][w],tr[0][w])]=1;
            if(tr[0][w]&&key[v]&&key[u])mat[id(u,v)][id(tr[0][w],tr[0][w])]=1;
        }
        int k=(tot+1)*(tot+1);

        vector<int> res,valid_id;
        f(i,0,tot)f(j,0,tot)if(key[i]&&key[j])valid_id.push_back(id(i,j));
        dp[0][0]=1;
        f(i,1,78) {
            f(j, 0, k)f(x, 0, k)dp[i][j] = (dp[i][j] + (ll) dp[i - 1][x] * mat[x][j]) % mod;
            ll ans=0;
            for(auto I:valid_id)ans+=dp[i][I];
            res.push_back(ans%mod);
        }
        printf("%lld\n", linear_seq::gao(res, m - 1) % mod);
    }
}T;
char s[N];
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef local
    freopen("../in.txt", "r", stdin);
    clock_t beg=clock();
#endif
    int n,m;cin>>n>>m;
    f(i,1,n){
        cin>>s+1;
        T.insert(s);
    }
    T.build_mat(m);
    debug(clock()-beg);
}

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 22;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

typedef vector<vector<modint>> mat;
typedef vector<modint> vec;
mat mtmul(mat& A, mat& B) {
	mat C(A.size(), vec(B[0].size()));
	rep(i, (int)A.size()) {
		rep(k, (int)B.size()) {
			rep(j, (int)B[0].size()) {
				C[i][j] += A[i][k] * B[k][j];
			}
		}
	}
	return C;
}
mat mtpow(mat A, ll n) {
	mat B(A.size(), vec(A.size()));
	rep(i, (int)A.size()) {
		B[i][i] = 1;
	}
	while (n > 0) {
		if (n & (ll)1)B = mtmul(B, A);
		A = mtmul(A, A);
		n >>= 1;
	}
	return B;
}
void solve() {
	int n, m; cin >> n >> m;
	vector<string> s(n);
	rep(i, n)cin >> s[i];
	vector<int> ad(n);
	int c = 0;
	rep(i, n) {
		ad[i] = c; c += s[i].size();
	}
	vector<int> islas(c* c,0);
	rep(i, n)rep(j, n) {
		islas[(ad[i] + s[i].size() - 1) * c + (ad[j] + s[j].size() - 1)] = 1;
	}
	vector<vector<int>> G(c* c+1);
	rep(i, n)rep(j, s[i].size())rep(k, n)rep(l, s[k].size()) {
		int x = ad[i] + j;
		int y = ad[k] + l;
		int z = x * c + y;
		if (islas[z])continue;
		rep(a, 26) {
			char t = 'a' + a;
			if (j + 1 < s[i].size()) {
				if (s[i][j + 1] != t)continue;
			}
			if (l + 1 < s[k].size()) {
				if (s[k][l + 1] != t)continue;
			}
			if (j + 1 < s[i].size() && l + 1 < s[k].size()) {
				int to = (ad[i] + j + 1) * c + (ad[k] + l + 1);
				if (islas[to])to = c * c;
				G[z].push_back(to);
			}
			else if (j + 1 < s[i].size()) {
				rep(nk, n) {
					if (s[nk][0] != t)continue;
					int to = (ad[i] + j + 1) * c + ad[nk];
					if (islas[to])to = c * c;
					G[z].push_back(to);
				}
			}
			else if (l + 1 < s[k].size()) {
				rep(nj, n) {
					if (s[nj][0] != t)continue;
					int to = (ad[nj]) * c + ad[k] + l + 1;
					if (islas[to])to = c * c;
					G[z].push_back(to);
				}
			}
			else {
				rep(nj, n){
					if (s[nj][0] != t)continue;
					rep(nk, n) {
						if (s[nk][0] != t)continue;
						int to = (ad[nj]) * c + ad[nk];
						if (islas[to])to = c * c;
						G[z].push_back(to);
					}
				}
			}
		}
	}
	rep(i, n)rep(j, n) {
		if (s[i][0] == s[j][0]) {
			int z = ad[i] * c + ad[j];
			if (islas[z]) {
				z = c * c; //cout << "??\n";
			}
			G[c * c].push_back(z);
		}
	}
	vector<bool> can(c * c+1);
	queue<int> q;
	q.push(c* c); can[c * c] = true;
	while (!q.empty()) {
		int v = q.front(); q.pop();
		for (int to : G[v]) {
			if (!can[to]) {
				can[to] = true;
				q.push(to);
			}
		}
	}
	rep(i, n)rep(j, s[i].size())rep(k, n)rep(l, s[k].size()) {
		int z = (ad[i] + j) * c + (ad[k] + l);
		for (int t = 1; j + t < s[i].size() && l + t < s[k].size(); t++) {
			if (s[i][j + t] != s[k][l + t])can[z] = false;
		}
	}
	vector<int> ids;
	vector<int> trans(c * c+1, -1);
	rep(i, c * c+1) {
		if (can[i]) {
			trans[i] = ids.size();
			ids.push_back(i);
		}
	}
	mat A(ids.size(), vector<modint>(ids.size()));
	rep(i, c * c+1)for (int to : G[i]) {
		if (can[i] && can[to]) {
			A[trans[to]][trans[i]] = 1;
		}
	}
	A = mtpow(A, m);
	modint ans = A[ids.size() - 1][ids.size() - 1];
	cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}