#include "bits/stdc++.h"
#include <random>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
typedef vector<ll> V;
#define rep(i, n) for(ll (i) = 0; (i) < (n); (i)++)
#define rep1(i, n) for(ll (i) = 1; (i) <= (n); (i)++)
#define rrep(i, n) for(ll (i) = (n) - 1; (i) >= 0; (i)--)
#define rrep1(i, n) for(ll (i) = (n); (i) >= 1; (i)--)
template<class T> void chmax(T &a, const T &b){if(a < b){a = b;}}
template<class T> void chmin(T &a, const T &b){if(a > b){a = b;}}
const int TIMELIMIT = 2850;

class Pair{
    public:
    string s;
    ll score;
};

class Point{
    public:
    int x, y;
    Point(int x = 0, int y = 0):x(x), y(y){};
    Point operator + (const Point p) {
        return Point((x + p.x)%20, (y + p.y)%20);
    }
};

class Board{
    private:
    std::vector<std::vector<char> > m;
    public:
    void init(){
        m = vector<vector<char> >(20, vector<char>(20, '.'));
    }
    void show(){
        rep(y, 20){
            rep(x, 20)cout << m[y][x];
            cout << endl;
        }
    }
    std::vector<char> operator[] (const int i) const {return m[i];};
    std::vector<char>& operator[] (const int i) {return m[i];};
    char operator[] (const Point p) const {return m[p.y][p.x];};
    char& operator[] (const Point p) {return m[p.y][p.x];};

    bool isContain(Point p) const {
        return p.y != 20;
    }

    Point nextPoint(Point p) const {
        p.x++;
        if (p.x == 20) {
            p.x = 0;
            p.y++;
            if (p.y == 20)p.y=0;
        }
        return p;
    }

    Board(){
        init();
    }
};

ll N, M;
vector<string>str;
mt19937 mt;

bool putString(Board &board, const string &s){
    ll sLen = s.size();
    Point bestPoint(20, 20);
    ll bestScore = -1;
    ll bestDir = 0;
    Point rp(mt() % 20, mt() % 20);
    for (Point p = rp; ;) {
        ll widthScore = sLen;
        ll heightScore = sLen;
        rep(i, sLen) {
            Point wIdx(i, 0);
            if (board[p + wIdx] == '.')widthScore--;
            else if (board[p + wIdx] != s[i])widthScore -= 100;
            
            Point hIdx(0, i);
            if (board[p + hIdx] == '.')heightScore--;
            else if (board[p + hIdx] != s[i])heightScore -= 100;
        }
        if (widthScore >= 0 && widthScore > bestScore) {
            bestPoint = p;
            bestScore = widthScore;
            bestDir = 1;
        } 
        if (heightScore >= 0 && heightScore > bestScore) {
            bestPoint = p;
            bestScore = heightScore;
            bestDir = 2;
        }
        p = board.nextPoint(p);
        if (rp.x == p.x && rp.y == p.y)break;
    }
    if (bestDir == 0)return false;
    rep(i, sLen){
        Point idx(i, 0);
        if (bestDir == 2)idx = Point(0, i);
        board[bestPoint + idx] = s[i];
    }
    return true;
}

int main(){
    chrono::system_clock::time_point  start, end;
    start = chrono::system_clock::now(); // 計測開始時間
    random_device rd;
    mt = mt19937(rd());
    
    cin >> N >> M;
    str = vector<string>(M);
    rep(i, M)cin >> str[i];
    
    Board board;
    
    vector<Pair>pairVector(M);
    rep(i, M) {
        pairVector[i].s = str[i];
        ll cnt = 0;
        pairVector[i].score = 0;
        rep(j, M){
            if (str[i].find(str[j]) != string::npos) {
                cnt++;
            }
        }
        pairVector[i].score = cnt * 66528000;
        pairVector[i].score /= str[i].size();
        pairVector[i].score += cnt;
    }
    sort(pairVector.begin(), pairVector.end(), [](auto const& lhs, auto const& rhs) {
        return lhs.score > rhs.score;
    });
    rep(i, M) {
        putString(board, pairVector[i].s);
    }

    board.show();

    return 0;
    for (int step = 0;; step++) {
        end = std::chrono::system_clock::now();  // 計測終了時間
        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
        if(elapsed > TIMELIMIT)break;

    }




    return 0;
}


// Generated by 2.3.1 https://github.com/kyuridenamida/atcoder-tools

#include <bits/stdc++.h>
// #include "atcoder/all"

#define SUBMIT

using namespace std;

using i64 = long long;

const i64 MOD = 1e9 + 7;
const i64 INF = i64(1e18) + 7;


template <typename T>
bool chmin(T& x, T y){
    if(x > y){
        x = y;
        return true;
    }
    return false;
}

template <typename T>
bool chmax(T& x, T y){
    if(x < y){
        x = y;
        return true;
    }
    return false;
}


using Uint = uint64_t;

constexpr int n = 20;
array<Uint, n> h_res, w_res;

void solve(long long m, std::vector<std::string> s){

    // sort(s.begin(), s.end(), [](auto x, auto y){return x.size() < y.size();});
    int min_len = 100;
    int max_len = 0;

    vector<pair<int,Uint>> target(m);
    for(int i = 0; i < m; ++i){
        chmin(min_len, int(s[i].size()));
        chmax(max_len, int(s[i].size()));
        target[i].first = s[i].size();
        target[i].second = 0;
        for(int j = 0; j < s[i].size(); ++j){
            target[i].second |= ((s[i][j] - 'A') << (3 * j));
        }
    }

    for(int i = 0; i < n; ++i){
        for(int j = 0; j < n; ++j){
            Uint val = (rand() & 7);
            h_res[i] |= val << (j * 3);
            w_res[j] |= val << (i * 3);
        }
    }

    auto get = [&](int i, int j){
        Uint h = (h_res[i] >> (3 * j)) & 7;
        Uint w = (w_res[j] >> (3 * i)) & 7;
        assert(h == w);
        return h;
    };
    auto get_h = [&](int i, int j, int len){
        Uint h = (h_res[i] >> (3 * j)) & ((1uLL << (3 * len)) - 1);
        if(j + len > n){
            int over = j + len - n;
            return h | Uint((h_res[i] & ((1uLL << (3 * over)) - 1)) << (3 * (n - j)));
        }
        return h;
    };
    auto get_w = [&](int i, int j, int len){
        Uint w = (w_res[j] >> (3 * i)) & ((1uLL << (3 * len)) - 1);
        if(i + len > n){
            int over = i + len - n;
            return w | Uint((w_res[j] & ((1uLL << (3 * over)) - 1)) << (3 * (n - i)));
        }
        return w;
    };

    // TODO: hash_map
    vector<unordered_map<Uint, int>> now_hash(max_len + 1);
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < n; ++j){
            for(int l = min_len; l <= max_len; ++l){
                ++now_hash[l][get_h(i, j, l)];
                ++now_hash[l][get_w(i, j, l)];
            }
        }
    }


    // 以下回答関連
#ifndef SUBMIT
    int ans = 0;
    for(int i = 0; i < m; ++i){
        auto t = target[i];
        if(now_hash[t.first].count(t.second)){
            cout << "correct: " << i << "  " << s[i] << endl;
            ++ans;
        }
    }

    cout << "ans: " << ans << endl;
    cout << Uint(round(1e8 * ans / m)) << endl;
#endif

    for(int i = 0; i < n; ++i){
        for(int j = 0; j < n; ++j){
            cout << char('A' + ((h_res[i] >> (3 * j)) & 7));
        }
        cout << endl;
    }

    cout << endl;
}


signed main(){

#ifndef SUBMIT
    long long N;
    long long M;
    ifstream fs("../contests/ahc004/A/in/0001.txt");
    assert(fs.is_open());
    fs >> N >> M;
    std::vector<std::string> s(M);
    for(int i = 0 ; i < M ; i++){
        fs >> s[i];
    }
#else

    long long N;
    std::scanf("%lld", &N);
    long long M;
    std::scanf("%lld", &M);
    std::vector<std::string> s(M);
    for(int i = 0 ; i < M ; i++){
        std::cin >> s[i];
    }
#endif
    solve(M, std::move(s));
    return 0;
}
