A chainword is a special type of crossword. As most of the crosswords do, it has cells that you put the letters in and some sort of hints to what these letters should be.The letter cells in a chainword are put in a single row. We will consider chainwords of length $$$m$$$ in this task.A hint to a chainword is a sequence of segments such that the segments don't intersect with each other and cover all $$$m$$$ letter cells. Each segment contains a description of the word in the corresponding cells.The twist is that there are actually two hints: one sequence is the row above the letter cells and the other sequence is the row below the letter cells. When the sequences are different, they provide a way to resolve the ambiguity in the answers.You are provided with a dictionary of $$$n$$$ words, each word consists of lowercase Latin letters. All words are pairwise distinct.An instance of a chainword is the following triple:   a string of $$$m$$$ lowercase Latin letters;  the first hint: a sequence of segments such that the letters that correspond to each segment spell a word from the dictionary;  the second hint: another sequence of segments such that the letters that correspond to each segment spell a word from the dictionary. Note that the sequences of segments don't necessarily have to be distinct.Two instances of chainwords are considered different if they have different strings, different first hints or different second hints.Count the number of different instances of chainwords. Since the number might be pretty large, output it modulo $$$998\,244\,353$$$.

The first line contains two integers $$$n$$$ and $$$m$$$ ($$$1 \le n \le 8$$$, $$$1 \le m \le 10^9$$$) — the number of words in the dictionary and the number of letter cells. Each of the next $$$n$$$ lines contains a word — a non-empty string of no more than $$$5$$$ lowercase Latin letters. All words are pairwise distinct.

Print a single integer — the number of different instances of chainwords of length $$$m$$$ for the given dictionary modulo $$$998\,244\,353$$$.

NoteHere are all the instances of the valid chainwords for the first example:   The red lines above the letters denote the segments of the first hint, the blue lines below the letters denote the segments of the second hint.In the second example the possible strings are: "abab", "abcd", "cdab" and "cdcd". All the hints are segments that cover the first two letters and the last two letters.

#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;
}

// 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 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 <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;
}

// 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

#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;
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;

#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;

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;
}

#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<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;
}

// 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 <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;
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;

#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;
}

#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;
		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>
#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<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>
#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';
}

// 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;

#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;

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>
#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 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>

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;

#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>
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>
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;

#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 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);
}

#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 <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';
}

#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

// 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>
#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]);
}

#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);
}

//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 <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>

#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;
}

#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];
}

#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>

#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>
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 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

#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<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;
}

#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;
    }
}

#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>
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<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;
}
//?

/* 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;
}

#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]

// 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

#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;
}

#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;
}

// #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>
#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 <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;
}

#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<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;
}
/*
*/

#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 <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 <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;
#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;
}

#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 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;
}

//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;
}

#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 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 <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 <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>
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                                   //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////////

// 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;
}

// #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;
}

//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 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';
}

#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>
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;

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 <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;

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>
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;
}

#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;

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;

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;
#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 <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;
}

#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;
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 <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
*/

//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>
#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];
}

//#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;
#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>

#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;
}