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++ (judge verdict: Time Limit Exceeded)

#include <bits/stdc++.h>

using namespace std;

int N;

string concat(string s, string t) {
  int const ssize = s.size();
  int const tsize = t.size();
  string ret = s+t;
  for(int i=0; i<ssize; i++) {
    bool ok = true;
    for(int j=0; ; j++) {
      if(s[i+j] != t[j]) { ok = false; break; }
      if(i+j+1 == ssize) { break; }
      if(j+1 == tsize) { ok = false; break; }
    }
    if(ok) {
      if(i) ret = s.substr(0, i) + t;
      else  ret = t;
    }
  }
  return ret;
}

string arr[11];
map<int, string> mp;
string dfs(string& now, int S) {
  
  //if(mp.find(S) != mp.end()) return mp[S];
  
  string& ret = mp[S];
  if(S == (1<<N)-1) {
    return ret = now;
  }
  
  string tmp;
  for(int i=0; i<N; i++) {
    if((S>>i & 1)) continue;
    tmp = concat(now, arr[i]);
    tmp = dfs(tmp, S+(1<<i));
    if(ret.empty() || tmp.size() < ret.size()) { ret = tmp; }
  }
  
  return ret;
}

inline bool cmp(const string& a, const string& b) {
  if(a.size() == b.size()) return a<b;
  return a.size()<b.size();
}

int main() {
  
  while(cin >> N && N) {
    mp.clear();
    for(int i=0; i<N; i++) {
      cin >> arr[i];
    }

    string s;
    cout << dfs(s, 0) << endl;
  }
  
  return 0;
}