Problem:
Princess, a Cryptanalyst

お姫様の暗号解読

English text is not available in this practice contest.

ある貧乏な国のおてんばで勇敢なお姫様は，お忍びで出かけた町である日本語で書かれた古文書を手に入れた．お姫様は日本語ができるため，さっそくこの古文書を読んでみた．すると，驚くべき事が分かった．この古文書は，古の秘宝の在処を示していたのである．ところが，秘宝の在処は暗号になっており，容易には分からないようになっていた．そこでお姫様は，従者であるあなたに暗号の解読を手伝うように命令を下した．

あなたはお姫様を助けるため昼夜を問わず調査を行った．その結果，Shortest Secret String (SSS) と呼ばれる文字列が解読に重要な役割を果たすことがわかった．ここで SSS とは，N 個の単語全部を部分文字列として含み，なおかつその長さが最小であるような文字列である．

あなたの仕事は，N 個の単語から SSS を見つけ出す事である．

Input

入力は複数のデータセットで与えられる．データセットの初めの一行は，データセットに含まれる単語の数N(1≦N≦10)が与えられる．続くN行に単語が与えられる．最後のデータセットの後に，0のみを含む一行が与えられる．

なお，入力で与えられる単語はアルファベット小文字のみからなり，長さは高々10であることが保証されている．

Output

各データセットについてSSS を一行に出力せよ．また，複数ある場合は辞書式順序で最小のものを出力せよ．

Sample Input

4
apple
length
things
thin
2
icp
cpc
3
zeta
eta
alphabet
2
until
till
0

Output for the Sample Input

applengthings
icpc
zetalphabet
untill

Solution in C++11 (judge verdict: Wrong Answer)

#include<stdio.h>
#include <iostream>
#include <math.h>
#include <numeric>
#include <vector>
#include <map>
#include <functional>
#include <stdio.h>
#include <array>
#include <algorithm>
#include <string>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <queue>
#include<iomanip>
#include<bitset>
#include<stack>
#include<set>
#include<limits>
#include <complex>
using namespace std;


const int mod = 1000000007;
struct Mod {
public:
	int num;
	Mod() : num(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) { ; }
	Mod(int n) : num((n % mod + mod) % mod) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	assert(b.num != 0);
	return Mod(a) * inv(b);
}
Mod operator/=(Mod &a, const Mod b) {
	assert(b.num != 0);
	return a = a * inv(b);
}

#define MAX_N 1024000

Mod fact[MAX_N], factinv[MAX_N];
void init() {
	fact[0] = Mod(1); factinv[0] = 1;
	for (int i = 0; i < MAX_N - 1; ++i) {
		fact[i + 1] = fact[i] * Mod(i + 1);
		factinv[i + 1] = factinv[i] / Mod(i + 1);
	}
}
Mod comb(const int a, const int b) {
	return fact[a] * factinv[b] * factinv[a - b];
}


template<typename T>
vector<vector<T>> keisann(const vector<vector<T>>l, const vector<vector<T>>r) {
	vector<vector<T>>ans(l.size(), vector<T>(r[0].size()));
	assert(l[0].size() == r.size());
	for (unsigned int h = 0; h < l.size(); ++h) {
		for (unsigned int i = 0; i < r.size(); ++i) {
			for (unsigned int w = 0; w < r[0].size(); ++w) {

				ans[h][w] += l[h][i] * r[i][w];
			}
		}
	}
	return ans;
}
template<typename T>
vector<vector<T>>powgyou(vector<vector<T>>a, const long long int n) {
	assert(a.size() == a[0].size());
	if (!n) {
		vector<vector<T>>e(a.size(), vector<T>(a[0].size()));
		for (unsigned int i = 0; i < a.size(); ++i) {
			e[i][i] = 1;
		}
		return e;
	}
	if (n == 1)return a;
	else {
		vector<vector<T>>ans(a.size(), vector<T>(a[0].size(), 0));
		ans = powgyou(a, n / 2);
		ans = keisann(ans, ans);
		if (n % 2) {
			ans = keisann(ans, a);
		}
		return ans;
	}
}

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()

const int INF = 2147483647;
const long long int L_INF = 9223372036854775807;

typedef int Weight;
struct Edge {
	int src, dst;
	Weight weight;
	Edge(int src, int dst, Weight weight) :
		src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
	return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
	e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;
#define RESIDUE(s,t) (capacity[s][t]-flow[s][t])

vector<pair<int, int>>uses;

//流量0の逆辺も張らないと正しく求まらないので注意
Weight maximumFlow(const Graph &ag, int s, int t) {

	Graph g(ag);
	for (int i = 0; i < ag.size(); ++i) {
		for (int j = 0; j < ag[i].size(); ++j) {
			int d = ag[i][j].dst;
			int s = ag[i][j].src;
			
			bool ok = false;
			for (int k = 0; k < ag[d].size(); ++k) {
				if (ag[d][k].src == s) {
					ok = true;
					break;
				}
			}
			if (!ok) {
				g[d].push_back(Edge(d, s, 0));
			}
		}
	}

	int n = g.size();
	Matrix flow(n, Array(n)), capacity(n, Array(n));
	REP(u, n) FOR(e, g[u]) capacity[e->src][e->dst] += e->weight;

	Weight total = 0;
	while (1) {
		queue<int> Q; Q.push(s);
		vector<int> prev(n, -1); prev[s] = s;
		while (!Q.empty() && prev[t] < 0) {
			int u = Q.front(); Q.pop();
			FOR(e, g[u]) if (prev[e->dst] < 0 && RESIDUE(u, e->dst) > 0) {
				prev[e->dst] = u;
				Q.push(e->dst);
			}
		}
		if (prev[t] < 0) return total; // prev[x] == -1 <=> t-side
		Weight inc = INF;
		for (int j = t; prev[j] != j; j = prev[j])
			inc = min(inc, RESIDUE(prev[j], j));
		for (int j = t; prev[j] != j; j = prev[j])
			flow[prev[j]][j] += inc, flow[j][prev[j]] -= inc;
		total += inc;
	}
}

map<long long int, int>soinnsuu(long long int a) {
	map<long long int, int>ans;
	for (long long i = 2; i*i <= a; ++i) {
		while (a%i == 0) {
			ans[i]++;
			a /= i;
		}
	}
	if (a != 1)ans[a]++;


	return ans;
}

bool isso(long long int a) {
	if (a == 1)return false;
	for (long long int i = 2; i*i <= a;++i) {
		if (!(a%i)) {
			return false;
		}
		else {
		}
	}
	return true;
}

struct vert {
	int deg;
	int s;
	int id;
	vert(int a, int b, int c) {
		deg = a;
		s = b;
		id = c;
	}
};



vector<vector<int>>kaburis;

vector<string>nsts;

pair<string,long long int> memo[1024][10];

pair<string,long long int> getans(bitset<10>bs,int fin) {
	if (memo[bs.to_ulong()][fin].second >= 0) {
		return {memo[bs.to_ulong()][fin]};
	}
	if (bs.count() == 0) {
		return memo[bs.to_ulong()][fin] = { "",0 };
	}
	else if (bs.count() == 1) {
		for (int i = 0; i < 10; ++i) {
			if (bs[i]) {
				return memo[bs.to_ulong()][fin] = { nsts[i], 0 };
			}
		}
	}
	long long int amax = 0;
	string ansst;
	for (int i = 0; i < 10; ++i) {
		if (i==fin) {
			bs[i] = false;
			for (int j = 0; j < 10; ++j) {
				if (bs[j]) {
					
					if (amax < getans(bs, j).second + kaburis[j][i]) {
						amax = max(amax, getans(bs, j).second + kaburis[j][i]);
						ansst = getans(bs, j).first + nsts[fin].substr(kaburis[j][i], nsts[fin].size() - kaburis[j][i]);
					}
					else if (amax == getans(bs, j).second + kaburis[j][i]) {
						amax = max(amax, getans(bs, j).second + kaburis[j][i]);
						ansst = min(ansst, getans(bs, j).first + nsts[fin].substr(kaburis[j][i], nsts[fin].size() - kaburis[j][i]));
					}
				}
			}
			bs[i] = true;
		}
	}
	return memo[bs.to_ulong()][fin] = { ansst,amax };
}

int main() {
	
	//int N; cin >> N;
	//vector<vector<int>>edges(N);
	//vector<vert>es;
	//for (int i = 0; i < N; ++i) {
	//	int degree, s; cin >> degree >> s;
	//	es.push_back(vert(degree,s,i));
	//}
	//vector<vert>sortes(es);
	////sort(sortes.begin(), sortes.end(), [](const vert&l, vert&r) {return l.deg < r.deg; });
	//for (int i = 0; i < sortes.size(); ++i) {
	//	if (sortes[i].deg == 1) {
	//		int  nowid(i);
	//		while (sortes[nowid].deg == 1) {
	//			sortes[nowid].deg--;
	//			edges[nowid].push_back(sortes[nowid].s);
	//			sortes[sortes[nowid].s].s ^= sortes[nowid].id;
	//			sortes[sortes[nowid].s].deg--;
	//			nowid = sortes[sortes[nowid].s].id;
	//		}
	//	}
	//}
	//int ans = 0;
	//for (int i = 0; i < N; ++i) {
	//	for (int j = 0; j < edges[i].size(); ++j) {
	//		ans++;
	//	}
	//}
	//cout << ans << endl;
	//for (int i = 0; i < N; ++i) {
	//	for (int j = 0; j < edges[i].size(); ++j) {
	//		cout << i << " " << edges[i][j] << endl;
	//	}
	//}

	/*int n; cin >> n;
	vector<int>sinsuus(n);
	for (int j = 0; j < 2; ++j) {


		vector<int>nums;
		for (int i = 0; i < n; ++i) {
			int a; cin >> a;
			nums.push_back(a);
		}


		for (int i = 0; i < n; ++i) {
			int pl = get(nums[i], nums[i]);
			update(nums[i], n, 1);
			sinsuus[i] += nums[i] - (pl);
		}
		int k;
		for (int i = 0; i < 2 * N; ++i) {
			seg[i] = NODE();
		}
	}
	for (int i = n- 1; i >= 0; --i) {
		if (sinsuus[i] >= n-i) {
			if(i!=0)
				sinsuus[i- 1]++;
			sinsuus[i] -= n-i;
		}
	}

	vector<int>ansnums(n);



	for (int i = 0; i < n; ++i) {
		ansnums[i] = sinsuus[i]+get(0,sinsuus[i]-1);
		update(sinsuus[i], sinsuus[i], 1);
	}
	
	return 0;*/

	//5:10
	while (1) {
		for (int i = 0; i < 1024; ++i) {
			for (int j = 0; j < 10; ++j) {
				memo[i][j] = { "",-1 };
			}
		}
		int n; cin >> n;
		if (!n)break;
		vector<string>sts;
		for (int i = 0; i < n; ++i) {
			string st; cin >> st;
			sts.push_back(st);
		}
		vector<bool>oks(n, true);
		for (int i = 0; i < sts.size(); ++i) {
			for (int j = 0; j < sts.size(); ++j) {
				if (i != j) {
					if (sts[i].find(sts[j])!=string::npos) {
						oks[j] = false;
					}
				}
			}
		}
		nsts.clear();
		for (int i = 0; i < n; ++i) {
			if (oks[i]) {
				nsts.push_back(sts[i]);
			}
		}

		kaburis.resize(nsts.size());
		for (int i = 0; i < nsts.size(); ++i) {
			kaburis[i].resize(nsts.size());
		}

		for (int i = 0; i < nsts.size(); ++i) {
			for (int j = 0; j < nsts.size(); ++j) {
				if (i != j) {
					int k = min(nsts[i].size(),nsts[j].size())-1;
					string a = nsts[i].substr(nsts[i].size() - k, k);
					string b = nsts[j].substr(0, k);
					while (nsts[i].substr(nsts[i].size() - k, k) != nsts[j].substr(0, k)) {
						k--;
					}
					kaburis[i][j] = k;
				}
			}
		}
		int kaburinum = -1;
		string ansst;
		for (int i = 0; i < nsts.size(); ++i) {
			if (kaburinum < getans(bitset<10>((1 << nsts.size()) - 1), i).second) {
				kaburinum = getans(bitset<10>((1 << nsts.size()) - 1), i).second;
				ansst = getans(bitset<10>((1 << nsts.size()) - 1), i).first;
			}else if (kaburinum == getans(bitset<10>((1 << nsts.size()) - 1), i).second) {
				ansst = min(ansst,getans(bitset<10>((1 << nsts.size()) - 1), i).first);
			}
		}
		cout << ansst << endl;
	}
	return 0;
}