#include <iostream>
#include <sstream>
#include <vector>
#include <list>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
using namespace std;

typedef vector <string> VS;

const int nsize = 11;
int C[nsize][nsize];
string dp[nsize][1<<nsize];
const string inf = string( nsize * nsize, 'Z' );

bool include( string a, string b ) {
    // true: a has b
    int as = a.size();
    int bs = b.size();
    if ( as < bs ) return false;
    return a.find( b ) != string::npos;
}

VS convert( VS S ) {
    VS T;
    sort( S.begin(), S.end() );
    VS::iterator it = unique( S.begin(), S.end() );
    S.erase( it, S.end() );
    int n = S.size();
    for ( int i = 0; i < n; ++ i ) {
        bool flag = true;
        for ( int j = 0; j < n; ++ j ) {
            if ( i == j ) continue;
            if ( include( S[j], S[i] ) ) flag = false;
        }
        if ( flag ) {
            T.push_back( S[i] );
        }
    }
    return T;
}

int calc( string a, string b ) {
    int answer = 0;
    int n = min( a.size(), b.size() );
    reverse( a.begin(), a.end() );
    for ( int i = 0; i <= n; ++ i ) {
        string s = a.substr( 0, i );
        reverse( s.begin(), s.end() );
        if ( s == b.substr( 0, i ) ) {
            answer = max( answer, i );
        }
    }
    return answer;
}

string get_sub( string s, int c ) {
    return s.substr( c );
}

string min_str( string a, string b ) {
    if ( a.size() == b.size() ) {
        return a < b ? a : b;
    } else {
        return a.size() < b.size() ? a : b;
    }
}

bool check( string a, string b ) {
    if ( a.size() == b.size() ) {
        return a >= b;
    } else {
        return a.size() >= b.size();
    }
}

string min_element_str( VS W ) {
    int n = W.size();
    for ( int i = 0; i + 1 < n; ++ i ) {
        for ( int j = i + 1; j < n; ++ j ) {
            if ( check( W[i], W[j] ) ) {
                swap( W[i], W[j] );
            }
        }
    }
    return W[0];
}

int main() {
    int n;
    while ( cin >> n && n ) {
        VS W;
        string w;
        for ( int i = 0; i < n; ++ i ) {
            cin >> w;
            W.push_back( w );
        }

        W = convert( W );
        n = W.size();
        for ( int i = 0; i < n; ++ i ) {
            for ( int j = 0; j < n; ++ j ) {
                C[i][j] = calc( W[i], W[j] );
            }
        }

        int m = 1 << n;
        for ( int i = 0; i < n; ++ i ) {
            for ( int j = 0; j < m; ++ j ) {
                dp[i][j] = inf;
            }
        }
        for ( int i = 0; i < n; ++ i ) {
            dp[i][1<<i] = W[i];
        }
        for ( int i = 0; i < m; ++ i ) { // state
            for ( int j = 0; j < n; ++ j ) { // prev
                if ( dp[j][i] == inf ) continue;
                for ( int k = 0; k < n; ++ k ) { // next
                    if ( i & 1 << k ) continue;
                    int s = i;
                    int ns = i | 1 << k;
                    string t = dp[j][s] + get_sub( W[k], C[j][k] );
                    dp[k][ns] = min_str( dp[k][ns], t );
                }
            }
        }
        string answer = inf;
        for ( int i = 0; i < n; ++ i ) {
            answer = min_str( answer, dp[i][m-1] );
        }
        cout << answer << endl;
    }
    return 0;
}

Measured memory_bytes: 0