#include <bits/stdc++.h>

using namespace std;

/*
 /\_/\  /\_/\  /\_/\  /\_/\
( o.o )( o.o )( o.o )( o.o )
 > ^ <  > ^ <  > ^ <  > ^ <
 /\_/\                /\_/\
( o.o )   ghelopax   ( o.o )
 > ^ <                > ^ <
 /\_/\  /\_/\  /\_/\  /\_/\
( o.o )( o.o )( o.o )( o.o )
 > ^ <  > ^ <  > ^ <  > ^ <
*/

#define ll long long
#define ldb long double

const int maxN = 8;
const int maxLen = 10;
const int maxL = 100;
const int APB = 26;
const ll MOD = 998244353;
const int INF = 1e9;
const ll INFLL = 4e18;
const int LG = 20;

#define el "\n"
#define pb push_back
#define eb emplace_back
#define MASK(i) (1LL << (i))
#define BIT(msk, i) (((msk) >> (i)) & 1LL)
#define MID(l, r) ((l) + (((r) - (l)) >> 1))
#define lsb(x) ((x) & -(x))
#define FOR(i, l, r) for (int i = (l); i <= (int)(r); ++i)
#define FORLL(i, l, r) for (ll i = (l); i <= (ll)(r); ++i)
#define isz(v) (int)v.size()

void add(ll &x, ll w)
{
    x += w;
    if (x > MOD) x -= MOD;
}

int N, L;
vector<string> inp;

void input()
{
    cin >> N >> L;

    FOR(i, 1, N)
    {
        string s; cin >> s;
        inp.pb(s);
    }
}

namespace Subtask_1
{
    const int NodeCnt = maxN * maxLen;

    bool constraint()
    {
        return true;
    }

    struct Trie
    {
        struct Node
        {
            int nxt[APB];
            int id;
        } T[NodeCnt + 5];

        Trie()
        {
            memset(T[0].nxt, -1, sizeof(T[0].nxt));
            T[0].id = -1;
        }

        int cnt = 0;

        int newnode()
        {
            ++cnt;
            memset(T[cnt].nxt, -1, sizeof(T[cnt].nxt));
            T[cnt].id = -1;
            return cnt;
        }

        void insert(int id, string s)
        {
            int u = 0;
            for (char ch : s)
            {
                int c = ch - 'a';

                if (T[u].nxt[c] == -1)
                    T[u].nxt[c] = newnode();

                u = T[u].nxt[c];
            }

            T[u].id = id;
        }

        bool exist(int u, int c) { return T[u].nxt[c] != -1; }
        int next(int u, int c) { return T[u].nxt[c]; }
    };

    struct Aho_Corasick
    {
        Trie trie;
        int fail[NodeCnt + 5];
        int aut[NodeCnt + 5][APB];
        int exit[NodeCnt + 5];

        void insert(int id, string s)
        {
            trie.insert(id, s);
        }

        void build()
        {
            queue<int> q;

            fail[0] = 0;
            exit[0] = 0;
            FOR(c, 0, APB - 1)
            {
                int v = trie.next(0, c);
                if (v == -1) aut[0][c] = 0;
                else
                {
                    aut[0][c] = v;
                    fail[v] = 0;
                    exit[v] = 0;
                    q.push(v);
                }
            }

            while (!q.empty())
            {
                int u = q.front(); q.pop();
                FOR(c, 0, APB - 1)
                {
                    int v = trie.next(u, c);
                    if (v == -1) aut[u][c] = aut[fail[u]][c];
                    else 
                    {
                        fail[v] = aut[fail[u]][c];
                        exit[v] = (trie.T[fail[v]].id == -1 ? exit[fail[v]] : fail[v]);
                        aut[u][c] = v;
                        q.push(v);
                    }
                }
            }
        }

        vector<int> getid(int u)
        {
            vector<int> res;
            while (u != 0)
            {
                res.pb(trie.T[u].id);
                u = exit[u];
            }
            return res;
        }
    };

    struct LexicographicDP
    {
        Aho_Corasick ac;
        ll dp[maxL + 5][NodeCnt + 5][MASK(maxN) + 5];

        void init()
        {
            FOR(i, 0, N - 1)
                ac.insert(i, inp[i]);
            
            ac.build();
            
            memset(dp, -1, sizeof(dp));
        }

        ll count(int pos, int u, int msk)
        {
            ll &memo = dp[pos][u][msk];
            if (memo != -1) return memo;
            if (pos == L) return (msk == MASK(N) - 1);

            memo = 0;
            FOR(c, 0, APB - 1)
            {
                int v = ac.aut[u][c];
                vector<int> ids = ac.getid(v);
                int _msk = msk;
                if (!ids.empty()) for (int id : ids)
                    _msk |= MASK(id);

                add(memo, count(pos + 1, v, _msk));
            }

            return memo;
        }
    } lxc;
    
    void preprocess()
    {
        lxc.init();
    }

    void solve() // or: void query()
    {
        cout << lxc.count(0, 0, 0);
    }

    void run()
    {
        preprocess();
        solve(); // or: while(Q--) query();
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    // freopen(".inp", "r", stdin);
    // freopen(".out", "w", stdout);

    input();

    if (Subtask_1::constraint()) return Subtask_1::run(), 0;

    return 0;
}