#include<iostream>
#include<vector>
#include<bitset>
#include<algorithm>
using namespace std;
unsigned xorshift()
{
	static unsigned y=2463534242;
	y^=y<<13;
	y^=y>>17;
	y^=y<<5;
	return y;
}
const int N=20;
int M;
string S[800];
string outH[N],outW[N];
int G[800][800];
using bit=bitset<800>;
bit rest;
bit can[N+1][800];
int cnt[800];
int main()
{
	cin>>M>>M;
	vector<int>idx(M);
	for(int i=0;i<M;i++)
	{
		cin>>S[i];
		rest[i]=1;
		cnt[i]=1;
		idx[i]=i;
	}
	sort(idx.begin(),idx.end(),[](int i,int j){return S[i].size()<S[j].size();});
	for(int i:idx)for(int j:idx)if(i!=j&&rest[j])
	{
		for(int k=1;k<=S[i].size();k++)
		{
			int len=S[i].size()-k;
			if(S[j].size()<len)len=S[j].size();
			if(S[i].substr(k,len)==S[j].substr(0,len))
			{
				G[i][j]=S[j].size()-len;
				if(G[i][j]==0)
				{
					rest[j]=0;
					cnt[i]+=cnt[j];
					cnt[j]=0;
				}
				break;
			}
		}
	}
	for(int tm=0;tm<N;tm++)
	{
		string now="";
		if(rest.any())
		{
			vector<vector<int> >dist(N+1,vector<int>(M,0));
			vector<vector<int> >pr(N+1,vector<int>(M,-1));
			for(int v=0;v<M;v++)if(rest[v])
			{
				for(int u=S[v].size();u<=N;u++)
				{
					dist[u][v]=cnt[v];
					can[u][v]=rest;
					can[u][v][v]=0;
				}
			}
			for(int u=0;u<N;u++)for(int v=0;v<M;v++)if(dist[u][v])
			{
				for(int w=0;w<M;w++)if(can[u][v][w])
				{
					int nu=u+G[v][w];
					if(nu<=N&&dist[nu][w]<dist[u][v]+cnt[w])
					{
						dist[nu][w]=dist[u][v]+cnt[w];
						pr[nu][w]=v;
						can[nu][w]=can[u][v];
						can[nu][w][w]=0;
					}
				}
			}
			int go=-1;
			for(int v=0;v<M;v++)if(go==-1||dist[N][v]>dist[N][go])go=v;
			vector<int>vs;
			{
				int nu=N;
				while(true)
				{
					vs.push_back(go);
					int ngo=pr[nu][go];
					if(ngo<0)break;
					nu-=G[ngo][go];
					go=ngo;
				}
			}
			now=S[go];
			for(int i=vs.size()-1;i--;)
			{
				int d=G[go][vs[i]];
				go=vs[i];
				now+=S[go].substr(S[go].size()-d);
			}
		}
		while(now.size()<N)now+='.';
		cout<<now<<endl;
		outW[tm]=now+now;
		for(int j=0;j<N;j++)outH[j]+=now[j];
		for(int i=0;i<M;i++)if(rest[i])
		{
			for(int k=0;k<N;k++)if(outW[tm].substr(k,S[i].size())==S[i])
			{
				rest[i]=0;
				break;
			}
			if(rest[i]&&tm+1>=S[i].size())
			{
				for(int j=0;j<N;j++)if(outH[j].substr(tm+1-S[i].size())==S[i])
				{
					rest[i]=0;
					break;
				}
			}
		}
	}
}

#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <tuple>
#include <cstdint>
#include <cstdio>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <cassert>
#include <time.h>

#define rep(i, n) for(int i = 0; i < n; i++)
#define per(i, n) for(int i = n - 1; i >= 0; i--)
using ll = long long;
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define vd vector<double>
#define vvd vector<vd>
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pdi pair<double, int>
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
using namespace std;
constexpr int n = 20;
int m;
vector<string> s;
vector<deque<string>> ss(n + 1);
vvi board(n, vi(n));
void tekitou_sort(){
	rep(i, n){
		int nokori = n;
		while(true){
			bool found = false;
			for(int j = nokori; j >= 0; j--) if(!ss[j].empty()){
				found = true;
				rep(k, j) board[i][n-nokori+k] = ss[j][0][k] - 'A';
				nokori -= j;
				ss[j].pop_front();
				break;
			}
			if(!found) break;
		}
	}
}
void inputs(){
	cin >> m >> m;
	s.resize(m);
	rep(i, m) cin >> s[i];
}
int main(){
	srand(time(NULL));
	inputs();
	rep(i, m) ss[s[i].size()].push_back(s[i]);

	rep(i, n) rep(j, n) board[i][j] = rand() % 8;
	tekitou_sort();

	rep(i, n){
		rep(j, s[i].size()) board[i][j] = s[i][j] - 'A';
	}
	rep(i, n){
		rep(j, n) printf("%c", board[i][j] + 'A');
		printf("\n");
	}
}