//#define _GLIBCXX_DEBUG
#include <iostream>
#include <time.h>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <vector>
#include <algorithm>
#include <functional>
#include <random>
#include <string>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <bits/stdc++.h>
#include <deque>
#include <queue>
#include <list>

/*
vector<int> a(N);
vector<vector<int>> a(N, vector<int>(N));
auto itr = a.begin();
for (auto itr = a.begin(); itr != a.end(); itr++)
{
    cout << itr - a.begin() << endl; = 0,1,...,N-1
}
sort(a.begin(), a.end());
reverse(a.begin(), a.end());
*/

/*
list<int> lst;
lst.push_front(i);
lst.push_back(i);
lst.pop_front();
lst.pop_back();
for(auto itr = lst.begin(); itr != lst.end(); ++itr) {
    std::cout << *itr << "\n";
}
*/

/*
bool cmp(const std::pair<int, int> &a, const std::pair<int, int> &b)
{
    return a.first < b.first;
}
vector<pair<int, int>> p(N);
for (int i = 0; i < N; i++)
{
    p[i].first = a[i];
    p[i].second = b[i];
}
sort(p.begin(), p.end(), cmp);
for (int i = 0; i < N; i++)
{
    a[i] = p[i].first;
    b[i] = p[i].second;
}

struct Hara
{
    int A, B;
};

bool cmp(const Hara &a, const Hara &b)
{
    return a.A < b.A;
}

sort(h.begin(), h.end(), cmp);
*/

/*
std::unordered_set<int> hash;
*/

/*
struct Edge
{
    int to;
    long long w;
    Edge(int to, long long w) : to(to), w(w) {}
};
using Graph = vector<vector<Edge>>;
Graph G(N);
    for (int i = 0; i < M; ++i) {
        int a, b;
        long long w;
        cin >> a >> b >> w;
        G[a].push_back(Edge(b, w));
    }
*/

/*
struct Hara
{
    long long a, b;
};
bool operator<(const Hara &hara_1, const Hara &hara_2)
{
    return hara_1.b < hara_2.b;
}
*/

using namespace std;

const int MAX = 510000;
const int MOD = 1000000007;
const int INF = 1000000000;

long long fac[MAX], finv[MAX], inv[MAX];

// テーブルを作る前処理
void COMinit()
{
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (int i = 2; i < MAX; i++)
    {
        fac[i] = fac[i - 1] * i % MOD;
        inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
        finv[i] = finv[i - 1] * inv[i] % MOD;
    }
}

// 二項係数計算
long long COM(int n, int k)
{
    if (n < k)
        return 0;
    if (n < 0 || k < 0)
        return 0;
    return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}

long long GCD(long long m, long long n)
{
    if (m < n)
    {
        swap(m, n);
    }
    // ベースケース
    if (n == 0)
    {
        return m;
    }

    // 再帰呼び出し
    return GCD(n, m % n);
}

struct Hara
{
    string str;
    int len;
};

bool operator<(const Hara &hara_1, const Hara &hara_2)
{
    return hara_1.len < hara_2.len;
}

int main()
{
    int N, M;
    cin >> N >> M;
    vector<Hara> h(M);
    for (int i = 0; i < M; i++)
    {
        cin >> h[i].str;
        h[i].len = h[i].str.length();
    }

    sort(h.begin(), h.end());

    /*
    for (int i = 0; i < M; i++)
    {
        cout << h[i].str << endl;
    }
    */

    int p = 0;
    for (int i = 0; i < N; i++)
    {
        int len = 0;
        while (len < N)
        {
            if (len + h[p].len <= N)
            {
                cout << h[p].str;
                len += h[p].len;
                p++;
            }
            else
            {
                len++;
                cout << '.';
            }
        }
        cout << endl;
    }
}
#include<bits/stdc++.h>
#define REP(i,b,e) for(int i=b;i<e;i++)

std::vector<std::vector<int>> scc_decompose(
		std::vector<std::vector<int>> &links,
		std::vector<std::vector<int>> &rlinks
	){
	int n = links.size();
	int cnt = 0;
	std::vector<int> order;
	std::vector<bool> visited(n, false);
	std::function<void(int)> dfs = [&](int x){
		visited[x] = true;
		for(auto to: links[x]) if(!visited[to]) dfs(to);
		order.push_back(x);
	};

	for(int i=0; i<n; i++) if(!visited[i]) dfs(i);
	std::reverse(order.begin(), order.end());

	cnt = 0;
	std::vector<std::vector<int>> scc;
	std::fill(visited.begin(), visited.end(), false);
	dfs = [&](int x){
		visited[x] = true;
		for(auto to: rlinks[x]) if(!visited[to]) dfs(to);
		scc[cnt].push_back(x);
	};

	for(auto i: order) if(!visited[i]){
		scc.push_back(std::vector<int>());
		dfs(i);
		cnt++;
	}

	return scc;
}


std::vector<int> topological_sort(
		std::vector<std::vector<int>> &links,
		std::vector<std::vector<int>> &scc
	){
	int n = links.size();
	std::vector<int> scc_num(n);
	for(int i=0; i<scc.size(); i++){
		for(int &v: scc[i]) scc_num[v] = i;
	}
	
	std::vector<int> in_cnt(scc.size());
	std::vector<std::vector<int>> scc_links(scc.size());
	for(int i=0; i<links.size(); i++){
		for(int j: links[i]){
			if(scc_num[i]!=scc_num[j]){
				scc_links[scc_num[i]].push_back(scc_num[j]);
				in_cnt[scc_num[j]]++;
			}
		}
	}

	std::queue<int> que;
	for(int i=0; i<scc.size(); i++) if(in_cnt[i]==0) que.push(i);
	std::vector<int> ret;
	while(!que.empty()){
		int now = que.front();
		que.pop();
		ret.push_back(now);
		for(auto to: scc_links[now]){
			if(--in_cnt[to]==0) que.push(to);
		}
	}
	return ret;
}




int main(){
	int n, m;
	std::cin >> n >> m;
	std::string st[m];
	REP(i, 0, m) std::cin >> st[i];

	std::vector<std::vector<int>> links(m, std::vector<int>());
	std::vector<std::vector<int>> rlinks(m, std::vector<int>());
	REP(i, 0, m) REP(j, 0, m) {
		bool ok = false;
		REP(k, 0, st[i].size()){
			std::string s1 = st[i].substr(k);
			std::string s2 = st[j].substr(0, st[i].size()-k);
			if(s1 == s2) ok = true;
		}
		if(ok){
			links[i].push_back(j);
			rlinks[j].push_back(i);
		}
	}
	std::vector<std::vector<int>> scc = scc_decompose(links, rlinks);
	std::vector<int> order = topological_sort(links, scc);

	std::vector<std::string> ss;
	for(auto x: order) for(auto v: scc[x]) {
		ss.push_back(st[v]);
	}


	std::string ans[n];
	bool used[m] = {};

	REP(si, 0, m){

		int minrow = 0, crost = 50, min_add_len = ss[si].size();
		REP(i, 0, n){
			REP(j, 0, ans[i].size()){
				std::string s1 = ans[i].substr(j);
				std::string s2 = ss[si].substr(0, ans[i].size()-j);
				if(s1 != s2) continue;

				int pushlen = ss[si].size() - ans[i].size() + j;
				if(ans[i].size() + pushlen < n && min_add_len > pushlen){
					min_add_len = pushlen;
					minrow = i;
					crost = j;
				}
			}
		}

		crost = std::min<int>(crost, ans[minrow].size());
		std::string pushs = ss[si].substr(ans[minrow].size() - crost);
		while(minrow < n && ans[minrow].size() + pushs.size() > n) minrow++;
		if(minrow == n) continue;
		ans[minrow] += pushs;
		used[si] = true;

		//for(auto &s: ans) std::cout << s << '\n'; puts("");
	}

	


	REP(si, 0, m) if(!used[si]) {

		std::sort(ans, ans+n, [](std::string x, std::string y){
			return x.size() > y.size();
		});

		REP(j, 0, n){
			int ok_cnt = 0;
			REP(i, 0, n){
				if(ans[i].size() <= j) ok_cnt++;
			}
			if(ok_cnt < ss[si].size()) continue;

			int idx = 0;
			REP(i, 0, n){
				if(idx >= ss[si].size()) break;
				if(ans[i].size() <= j){
					ans[i] += std::string(j - ans[i].size(), '.');
					ans[i] += ss[si][idx];
					idx++;
				}
			}
			used[si] = true;
			break;
		}
	}

	for(auto &s: ans){
		if(s.size() < n){
			 s += std::string(n-s.size(), '.');
		}
	}

	for(auto &s: ans){
		std::cout << s << '\n';
	}
	return 0;
}


