#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#pragma GCC optimize ("Ofast,unroll-loops")
using namespace std;
ifstream cin ("adn.in");
ofstream cout ("adn.out");
int overlap[20][20];
int dp[1<<18][18];
int parent[1<<18][18];
int main() {
ios_base::sync_with_stdio(0);
int initial_n;
cin>>initial_n;
vector<string> temp(initial_n);
for (int i=0; i<initial_n; ++i) {
cin>>temp[i];
}
sort(temp.begin(), temp.end(), [](const string& a, const string& b) {
return a.length() > b.length();
});
vector<string> words;
for (int i=0; i<initial_n; ++i) {
bool ok=true;
for (string& w : words) {
if (w.find(temp[i]) != string::npos) {
ok=false;
break;
}
}
if (ok) {
words.push_back(temp[i]);
}
}
int n=words.size();
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
if (i!=j) {
int max_ov=0;
int max_possible=min(words[i].length(), words[j].length());
for (int len=1; len<=max_possible; ++len) {
if (words[i].substr(words[i].length()-len) == words[j].substr(0, len)) {
max_ov=len;
}
}
overlap[i][j]=max_ov;
}
}
}
int limit=(1<<n);
for (int mask=0; mask<limit; ++mask) {
for (int i=0; i<n; ++i) {
dp[mask][i]=1e9;
}
}
for (int i=0; i<n; ++i) {
dp[1<<i][i]=words[i].length();
}
for (int mask=1; mask<limit; ++mask) {
for (int i=0; i<n; ++i) {
if (dp[mask][i]==1e9) {
continue;
}
for (int j=0; j<n; ++j) {
if (!(mask & (1<<j))) {
int nxt=mask | (1<<j);
int cost=dp[mask][i]+words[j].length()-overlap[i][j];
if (cost < dp[nxt][j]) {
dp[nxt][j]=cost;
parent[nxt][j]=i;
}
}
}
}
}
int mask=limit-1, last=0, min_len=dp[mask][0];
for (int i=1; i<n; ++i) {
if (dp[mask][i] < min_len) {
min_len=dp[mask][i];
last=i;
}
}
vector<int> order;
while (mask > 0) {
order.push_back(last);
int p=parent[mask][last];
mask ^=(1<<last);
last=p;
}
reverse(order.begin(), order.end());
string ans=words[order[0]];
for (int i=1; i<order.size(); ++i) {
ans+=words[order[i]].substr(overlap[order[i-1]][order[i]]);
}
cout<<ans<<"\n";
}