#include <vector>
#include <array>
#include <stack>
#include <queue>
#include <list>
#include <bitset>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>
#include <random>
#include <cmath>
#include <cassert>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <sstream>

using namespace std;

const long long MOD = 998244353;

vector<vector<int>> matXmat(const vector<vector<int>>& A, const vector<vector<int>>& B, long long M = MOD) {
    int n = A.size();
    assert(n != 0);
    assert(A[0].size() == B.size());
    int l = B.size();
    assert(l != 0);
    int m = B[0].size();
    assert(m != 0);

    vector<vector<int>> res(n, vector<int>(m, 0));

    long long MOD2 = M * 1LL * M;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < l; ++j) {
            for (int k = 0; k < m; ++k) {
                res[i][k] += A[i][j] * 1LL * B[j][k] % M;
                if (res[i][k] >= M) {
                    res[i][k] -= M;
                }
                if (res[i][k] < 0) {
                    res[i][k] += M;
                }
            }
        }
    }
    return res;
}


vector<long long> __tmpA(500, 0);
vector<vector<int>> matXmat2(const vector<vector<int>>& A, const vector<vector<int>>& B, long long M = MOD) {
    int n = A.size();
    assert(n != 0);
    assert(A[0].size() == B.size());
    int l = B.size();
    assert(l != 0);
    int m = B[0].size();
    assert(m != 0);

    vector<vector<int>> res(n, vector<int>(m, 0));

    long long MOD2 = M * 1LL * M;
    for (int i = 0; i < n; ++i) {
        for (int k = 0; k < m; ++k) {
            __tmpA[k] = 0;
        }
        for (int j = 0; j < l; ++j) {
            for (int k = 0; k < m; ++k) {
                __tmpA[k] += A[i][j] * 1LL * B[j][k];
                if (__tmpA[k] >= MOD2) {
                    __tmpA[k] -= MOD2;
                }
            }
        }
        for (int k = 0; k < m; ++k) {
            if (__tmpA[k] >= MOD) {
                res[i][k] = __tmpA[k] % MOD;
            } else {
                res[i][k] = __tmpA[k];
            }
        }
    }
    return res;
}

vector<int> matXvec(const vector<vector<int>>& A, const vector<int>& B, long long M = MOD) {
    int n = A.size();
    assert(n != 0);
    int m = A[0].size();
    assert(m == B.size());

    vector<int> res(n, 0);

    long long MOD2 = M * 1LL * M;
    for (int i = 0; i < n; ++i) {
        long long ans = 0;
        for (int j = 0; j < m; ++j) {
            ans += A[i][j] * 1LL * B[j];
            if (ans >= MOD2) {
                ans -= MOD2;
            }
            if (ans < 0) {
                ans += MOD2;
            }
        }
        ans %= M;
        if (ans < 0) {
            ans += M;
        }
        res[i] = ans;
    }
    return res;
}

vector<vector<int>> matPow(vector<vector<int>> A, long long n, long long M = MOD) {
    int m = A.size();
    assert(m != 0 && A[0].size() == m);
    vector<vector<int>> res(m, vector<int>(m, 0));
    for (int i = 0; i < m; ++i) {
        res[i][i] = 1;
    }

    while (n > 0) {
        if (n & 1) {
            res = matXmat2(res, A, M);
        }
        A = matXmat2(A, A, M);
        n >>= 1;
    }
    return res;
}


class Trie{
    public:
        Trie(int n = 110000) : N(n), nodes(n), rt(-1), idx(-1) {
            rt = newNode();
        }

        void reset() {
            for (int i = 0; i <= idx; ++i) {
                nodes[i].reset();
            }
            idx = -1;
            rt = newNode();
        }


        int root() { return rt; }

        int index(char ch) {
            return ch - 'a';
        }

        void insert(string& s) {
            int cur = rt;
            for (auto c : s) {
                c = index(c);
                if (nodes[cur].nexts[c] == -1) {
                    nodes[cur].nexts[c] = newNode();
                }
                cur = nodes[cur].nexts[c];
                nodes[cur].cnt += 1;
            }
            nodes[cur].isEnd = true;
        }


        bool query(string& s) {
            int cur = rt;
            for (auto c : s) {
                c = index(c);
                if (nodes[cur].nexts[c] == -1) {
                    return false;
                }
                cur = nodes[cur].nexts[c];
            }
            return nodes[cur].isEnd;
        }

        int next(int r, char ch) {
            ch = index(ch);
            return nodes[r].nexts[ch];
        }

        bool isEnd(int u) {
            return nodes[u].isEnd;
        }


    private:
        const static int A = 26;
        struct Node {
            Node() : cnt(0), isEnd(false) { 
                fill(begin(nexts), end(nexts), -1);
            }

            void reset() {
                cnt = 0;
                isEnd = false;
                fill(begin(nexts), end(nexts), -1);
            }

            int nexts[A];
            int cnt;
            bool isEnd;
        };

        int N;
        int rt;
        int idx;
        vector<Node> nodes;

        int newNode() {
            return ++idx;
        }
};

class Solution {
public:
    long long solve(vector<string>& S, int m) {
        int n = S.size();

        Trie tr(2000);
        for (auto s : S) {
            tr.insert(s);
        }
        const int N = 100;
        vector<vector<vector<pair<int,int>>>> nexts(N, vector<vector<pair<int,int>>>(N));
        
        int rt = tr.root();
        vector<pair<int,int>> que;
        que.emplace_back(rt, rt);
        vector<vector<bool>> ok(N, vector<bool>(N, false));
        ok[rt][rt] = true;
        vector<vector<bool>> visited(N, vector<bool>(N, false));
        visited[rt][rt] = true;
        for (int i = 0; i < que.size(); ++i) {
            int u = que[i].first, v = que[i].second;

            for (int j = 'a'; j <= 'z'; ++j) {
                int nu = tr.next(u, j);
                int nv = tr.next(v, j);
                if (nu < 0 || nv < 0) {
                    continue;
                }
                if (tr.isEnd(nu) && tr.isEnd(nv)) {
                    nexts[u][v].emplace_back(rt, rt);
                }
                if (tr.isEnd(nu)) {
                    nexts[u][v].emplace_back(rt, nv);
                    if (!visited[rt][nv]) {
                        visited[rt][nv] = true;
                        que.emplace_back(rt, nv);
                    }
                }
                if (tr.isEnd(nv)) {
                    nexts[u][v].emplace_back(nu, rt);
                    if (!visited[nu][rt]) {
                        visited[nu][rt] = true;
                        que.emplace_back(nu, rt);
                    }
                }
                {
                    nexts[u][v].emplace_back(nu, nv);
                    if (!visited[nu][nv]) {
                        visited[nu][nv] = true;
                        que.emplace_back(nu, nv);
                    }
                }
            }
        }


        while (true) {
            int chg = 0;
            for (auto& p : que) {
                int u = p.first, v = p.second;
                if (ok[u][v]) {
                    continue;
                }
                for (auto& p2 : nexts[u][v]) {
                    int nu = p2.first, nv = p2.second;
                    if (ok[nu][nv]) {
                        ok[u][v] = true;
                        ++chg;
                        break;
                    }
                
                }
            }
            if (chg == 0) {
                break;
            }
        }

        map<pair<int,int>,int> indices;
        for (auto& p : que) {
            int u = p.first, v = p.second;
            if (ok[u][v]) {
                int idx = indices.size();
                indices[p] = idx;
            }
        }    
        int sz = indices.size();
        // cout << "sz " << sz << endl;
        vector<vector<int>> mat(sz, vector<int>(sz, 0));
        for (auto& p : que) {
            int u = p.first, v = p.second;
            if (ok[u][v]) {
                for (auto& p2 : nexts[u][v]) {
                    int nu = p2.first, nv = p2.second;
                    if (ok[nu][nv]) {
                        // cout << indices[p] << " " << indices[p2] << " " << u << " " << v <<  endl;
                        mat[indices[p2]][indices[p]] += 1;
                    }
                }
            }
        }

        auto M = matPow(mat, m);

        return M[0][0];
    }
};

int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);

    Solution sol;

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

    vector<string> S(n);
    for (int i = 0; i < n; ++i) {
        cin >> S[i];
    }

    cout << sol.solve(S, m) << '\n';

    return 0;
}