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: Time Limit Exceeded)

#include <bits/stdc++.h>

using namespace std;

string dp[11][1 << 10];
bool made[11][1 << 10] = {0};

void proc(string s, int i, int j) {
	if ( !made[i][j] || s.size() < dp[i][j].size() || (s.size() == dp[i][j].size() && s < dp[i][j]) ) {
		dp[i][j] = s;
	}
	made[i][j] = true;
}
string cat(string s1, string s2) {
	if (s1.size() >= s2.size()) {
		for (int i = 0; i <= s1.size()-s2.size(); ++i) {
			bool f = true;
			for (int j = 0; j < s2.size(); ++j) {
				if (s1[i+j] != s2[j]) {
					f = false;
					break;
				}
			}
			if (f) {
				return s1;
			}
		}
	}

	int len = 0;
	for (int k = min(s1.size(), s2.size()); k >= 0; --k) {
		bool f = true;
		for (int i = 0; i < k; ++i) {
			if (s1[s1.size()-k+i] != s2[i]) {
				f = false;
				break;
			}
		}
		if (f) {
			len = k;
			break;
		}
	}
	return s1 + s2.substr(len);
}

int N;
string s[10];
bool used[10] = {0};
string ans;
bool af;
void dfs(int n, string str) {
	if (n == N) {
		if ( !af || str.size() < ans.size() || (str.size() == ans.size() && str < ans) ) {
			ans = str;
			af = true;
		}
	}
	else {
		for (int i = 0; i < N; ++i) {
			if (!used[i]) {
				used[i] = true;
				dfs(n+1, cat(str, s[i]));
				used[i] = false;
			}
		}
	}
}
int main() {
	while ( cin >> N, N ) {
		for (int i = 0; i < N; ++i) {
			cin >> s[i];
		}
		af = false;
		dfs(0, "");
		cout << ans << endl;
/*
		fill(&made[0][0], &made[0][0]+11*(1 << 10), false);

		vector<string> s(N);
		for (int i = 0; i < N; ++i) {
			cin >> s[i];
		}
		made[0][0] = true; dp[0][0] = "";
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < (1 << N); ++j) {
				if (made[i][j]) {
					for (int k = 0; k < N; ++k) {
						if ((j & (1 << k)) == 0) {
							int nj = j | (1 << k);
							proc(cat(dp[i][j], s[k]), i+1, nj);
							proc(cat(s[k], dp[i][j]), i+1, nj);
						}
					}
				}
			}
		}
		cout << dp[N][(1 << N)-1] << endl;
*/
	}
}