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

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int INF = 110;
int main(){
  while (true){
    int N;
    cin >> N;
    if (N == 0){
      break;
    }
    vector<string> S(N);
    for (int i = 0; i < N; i++){
      cin >> S[i];
    }
    sort(S.begin(), S.end());
    S.erase(unique(S.begin(), S.end()), S.end());
    N = S.size();
    vector<string> T;
    for (int i = 0; i < N; i++){
      bool ok = true;
      int L1 = S[i].size();
      for (int j = 0; j < N; j++){
        if (i != j){
          int L2 = S[j].size();
          for (int k = 0; k <= L2 - L1; k++){
            if (S[j].substr(k, L1) == S[i]){
              ok = false;
            }
          }
        }
      }
      if (ok){
        T.push_back(S[i]);
      }
    }
    N = T.size();
    vector<vector<int>> d(N, vector<int>(N));
    for (int i = 0; i < N; i++){
      for (int j = 0; j < N; j++){
        int L1 = T[i].size();
        int L2 = T[j].size();
        for (int k = 0; k <= min(L1, L2); k++){
          if (T[i].substr(L1 - k) == T[j].substr(0, k)){
            d[i][j] = L2 - k;
          }
        }
      }
    }
    vector<vector<string>> dp(1 << N, vector<string>(N, string(INF, ' ')));
    for (int i = 0; i < N; i++){
      dp[1 << i][i] = T[i];
    }
    for (int i = 0; i < (1 << N); i++){
      for (int j = 0; j < N; j++){
        if ((i >> j & 1) == 1){
          for (int k = 0; k < N; k++){
            if ((i >> k & 1) == 0){
              int i2 = i | (1 << k);
              string t = dp[i][j] + T[k].substr(T[k].size() - d[j][k]);
              if (dp[i2][k].size() > t.size() || dp[i2][k].size() == t.size() && dp[i2][k] > t){
                dp[i2][k] = t;
              }
            }
          }
        }
      }
    }
    string ans(INF, ' ');
    for (int i = 0; i < N; i++){
    	if (ans.size() > dp[(1 << N) - 1][i].size() || ans.size() == dp[(1 << N) - 1][i].size() && ans > dp[(1 << N) - 1][i]){
    	  ans = dp[(1 << N) - 1][i];
    	}
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 5040
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

int dp[1<<14][14];
int len[14][14];

int main(){
    int n;
    while(cin >> n,n){
        for(int i=0;i<(1<<n);i++){
            for(int j=0;j<n;j++){
                dp[i][j]=1e9;
            }
        }
        vector<string> s(n);
        for(int i=0;i<n;i++){
            cin >> s[i];
        }
        sort(s.begin(), s.end());
        s.erase(unique(s.begin(), s.end()),s.end());
        n=s.size();
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i==j)len[i][j]=s[j].size();
                else{
                    int cnt=0;
                    int p=s[j].size();
                    for(int k=0;k<min(s[i].size(),s[j].size());k++){
                        if(s[j].substr(0,k+1)==s[i].substr((int)s[i].size()-1-k))cnt=k+1;
                    }
                    len[i][j]=p-cnt;
                }
            }
        }
        vector<bool> notuse(n,false);
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i==j)continue;
                for(int k=0;k+(int)(s[j].size())-1<s[i].size();k++){
                    if(s[i].substr(k,(int)(s[j].size()))==s[j])notuse[j]=true;
                }
            }
        }
        int aa=0;
        for(int i=0;i<n;i++){
            if(notuse[i])aa+=(1<<i);
        }
        for(int i=0;i<n;i++){
            if(notuse[i])continue;
            dp[aa+(1<<i)][i]=(int)s[i].size();
        }
        int res=1e9;
        for(int i=0;i<(1<<n);i++){
            for(int j=0;j<n;j++){
                if(dp[i][j]==1e9)continue;
                for(int k=0;k<n;k++){
                    if((1<<k)&i)continue;
                    dp[i+(1<<k)][k]=min(dp[i+(1<<k)][k],dp[i][j]+len[j][k]);
                }
            }
        }
        for(int i=0;i<n;i++){
            res=min(res,dp[(1<<n)-1][i]);
        }
        vector<string> V;
        auto con=[&](vector<int> id)->string{
            reverse(id.begin(), id.end());
            string ans=s[id[0]];
            for(int i=1;i<id.size();i++){
                int p=id[i-1],c=id[i];
                for(int j=(int)s[c].size()-len[p][c];j<(int)s[c].size();j++){
                    ans+=s[c][j];
                }
            }
            return ans;
        };
        auto dfs=[&](auto dfs,vector<int> &v,int bit,int last)->void{
            if(bit-(1<<last)==aa){
                V.push_back(con(v)); return;
            }
            for(int i=0;i<n;i++){
                if((1<<i)&aa)continue;
                if(i==last)continue;
                if((1<<i)&bit){
                    if(dp[bit-(1<<last)][i]+len[i][last]==dp[bit][last]){
                        v.push_back(i);
                        dfs(dfs,v,bit-(1<<last),i);
                        v.pop_back();
                    }
                }
            }
            return;
        };
        for(int i=0;i<n;i++){
            if((1<<i)&aa)continue;
            if(dp[(1<<n)-1][i]==res){
                vector<int> v={i};
                dfs(dfs,v,(1<<n)-1,i);
            }
        }
        sort(V.begin(), V.end());
        cout << V[0] << endl;
    }
}
accuracy: 1
time_ms: 480
memory_kb: 51140
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

int dp[1<<14][14];
int len[14][14];

int main(){
    int n;
    while(cin >> n,n){
        for(int i=0;i<(1<<n);i++){
            for(int j=0;j<n;j++){
                dp[i][j]=1e9;
            }
        }
        vector<string> s(n);
        for(int i=0;i<n;i++){
            cin >> s[i];
        }
        sort(s.begin(), s.end());
        s.erase(unique(s.begin(), s.end()),s.end());
        n=s.size();
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i==j)len[i][j]=s[j].size();
                else{
                    int cnt=0;
                    int p=s[j].size();
                    for(int k=0;k<min(s[i].size(),s[j].size());k++){
                        if(s[j].substr(0,k+1)==s[i].substr((int)s[i].size()-1-k))cnt=k+1;
                    }
                    len[i][j]=p-cnt;
                }
            }
        }
        vector<bool> notuse(n,false);
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i==j)continue;
                for(int k=0;k+(int)(s[j].size())-1<s[i].size();k++){
                    if(s[i].substr(k,(int)(s[j].size()))==s[j])notuse[j]=true;
                }
            }
        }
        int aa=0;
        for(int i=0;i<n;i++){
            if(notuse[i])aa+=(1<<i);
        }
        for(int i=0;i<n;i++){
            if(notuse[i])continue;
            dp[aa+(1<<i)][i]=(int)s[i].size();
        }
        int res=1e9;
        for(int i=0;i<(1<<n);i++){
            for(int j=0;j<n;j++){
                if(dp[i][j]==1e9)continue;
                for(int k=0;k<n;k++){
                    if((1<<k)&i)continue;
                    dp[i+(1<<k)][k]=min(dp[i+(1<<k)][k],dp[i][j]+len[j][k]);
                }
            }
        }
        for(int i=0;i<n;i++){
            res=min(res,dp[(1<<n)-1][i]);
        }
        vector<string> V;
        auto con=[&](vector<int> id)->string{
            reverse(id.begin(), id.end());
            string ans=s[id[0]];
            for(int i=1;i<id.size();i++){
                int p=id[i-1],c=id[i];
                for(int j=(int)s[c].size()-len[p][c];j<(int)s[c].size();j++){
                    ans+=s[c][j];
                }
            }
            return ans;
        };
        auto dfs=[&](auto dfs,vector<int> &v,int bit,int last)->void{
            if(bit-(1<<last)==aa){
                V.push_back(con(v)); return;
            }
            for(int i=0;i<n;i++){
                if((1<<i)&aa)continue;
                if(i==last)continue;
                if((1<<i)&bit){
                    if(dp[bit-(1<<last)][i]+len[i][last]==dp[bit][last]){
                        v.push_back(i);
                        dfs(dfs,v,bit-(1<<last),i);
                        v.pop_back();
                    }
                }
            }
            return;
        };
        for(int i=0;i<n;i++){
            if((1<<i)&aa)continue;
            if(dp[(1<<n)-1][i]==res){
                vector<int> v={i};
                dfs(dfs,v,(1<<n)-1,i);
            }
        }
        // for(int _=0;_<n;_++){
        //     if(res==dp[(1<<n)-1][_]){
        //         int curid=_,cur=(1<<n)-1;
        //         vector<int> id;
        //         while(1){
        //             id.push_back(curid);
        //             int nx=pre[cur][curid];
        //             if(nx<0)break;
        //             cur-=(1<<curid);
        //             curid=nx;
        //         }
        //         reverse(id.begin(), id.end());
        //         string ans=s[id[0]];
        //         for(int i=1;i<id.size();i++){
        //             int p=id[i-1];
        //             int c=id[i];
        //             for(int j=(int)s[c].size()-len[p][c];j<(int)s[c].size();j++){
        //                 ans+=s[c][j];
        //             }
        //         }
        //         v.push_back(ans);
        //     }
        // }

        sort(V.begin(), V.end());
        cout << V[0] << endl;
    }
}
accuracy: 1
time_ms: 480
memory_kb: 51168
final_rank: 17

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
const double pi = 3.141592653589793238462643383279;
using namespace std;
//typedef
//------------------------------------------
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<LL> VLL;
typedef vector<VLL> VVLL;

//container util
//------------------------------------------
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SQ(a) ((a) * (a))
#define EACH(i, c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define EXIST(s, e) ((s).find(e) != (s).end())
#define SORT(c) sort((c).begin(), (c).end())

//repetition
//------------------------------------------
#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define MOD 1000000007

#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define chmin(x, y) x = min(x, y)
#define chmax(x, y) x = max(x, y)
const double EPS = 1e-10, PI = acos(-1);
//ここから編集
struct RollingHash{

    using ull = unsigned long long;
    const ull mod = (1ULL << 61) - 1;
    const ull MASK30 = (1ULL << 30) - 1;
    const ull MASK31 = (1ULL << 31) - 1;

    const ull MASK61 = mod;

    ull base;
    int n;
    vector<ull> hash, pow;

    RollingHash(){}
    RollingHash(string s)
    {
        random_device rnd;
        mt19937_64 mt(rnd());
        base = MOD;
        
        n = (int)s.size();
        hash.assign(n+1, 0);
        pow.assign(n+1, 1);
        
        for(int i=0; i<n; i++){
            hash[i+1] = calc_mod(mul(hash[i], base) + s[i]);
            pow[i+1] = calc_mod(mul(pow[i], base));
        }
    }

    ull calc_mod(ull x){
        ull xu = x >> 61;
        ull xd = x & MASK61;
        ull res = xu + xd;
        if(res >= mod) res -= mod;
        return res;
    }

    ull mul(ull a, ull b){
        ull au = a >> 31;
        ull ad = a & MASK31;
        ull bu = b >> 31;
        ull bd = b & MASK31;
        ull mid = ad * bu + au * bd;
        ull midu = mid >> 30;
        ull midd = mid & MASK30;
        return calc_mod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    //[l,r)のハッシュ値
    inline ull get(int l, int r){
        ull res = calc_mod(hash[r] + mod*3-mul(hash[l], pow[r-l]));
        return res;
    }

    //string tのハッシュ値
    inline ull get(string t){
        ull res = 0;
        for(int i=0; i<t.size(); i++){
            res = calc_mod(mul(res, base)+t[i]);
        }
        return res;
    }

    //string s中のtの数をカウント
    inline int count(string t) {
        if(t.size() > n) return 0;
        auto hs = get(t);
        int res = 0;
        for(int i=0; i<n-t.size()+1; i++){
            if(get(i, i+t.size()) == hs) res++; 
        }
        return res;
    }

    inline ull concat(ull h1, ull h2, int h2len){
      return calc_mod(h2 + mul(h1, pow[h2len]));
    }

    // LCPを求める S[a:] T[b:]
    inline int LCP(int a, int b){
        int len = min((int)hash.size()-a, (int)hash.size()-b);
        
        int lb = -1, ub = len;
        while(ub-lb>1){
            int mid = (lb+ub)/2;

            if(get(a, a+mid) == get(b, b+mid)) lb = mid;
            else ub = mid;
        }
        return lb;
    }
    RollingHash& operator=(const RollingHash&) { return *this; }
};

bool max(const string& s, const string& t){
  
  if(s.size() < t.size()) return false;
  else if(s.size() > t.size()) return true;
  for(int i=0; i<s.size(); i++){
    if(s[i] > t[i]) return true;
    else if(s[i] < t[i]) return false;
  }
  return false;
}
int main()
{
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);
  
  int n; 
  while(cin >> n, n){
    vector<string> v(n);
    REP(i,n) cin >> v[i];
    REP(i,n) {
      RollingHash rh(v[i]);
      
    }
    vector<vector<string>> dp(n, vector<string>(1<<n, "~"));
    dp[0][0] = "";
    for(int i=0; i<n; i++){
      dp[i][(1<<i)] = v[i];
    }
    REP(bit,(1<<n)){

      for(int i=0; i<n; i++){
        if(dp[i][bit] == "~") continue;
        if(bit >> i & 1){

          for(int j=0; j<n; j++){
            if(!(bit >> j & 1)){

              /* dp[i][bit]にvjをくっつける */
              string s = dp[i][bit];
              string t = v[j];
              RollingHash rh(s);
              RollingHash rh2(t);
              int mx = 0;
              
              for(int k=1; k<=min(s.size(), t.size()); k++){
                if(rh.get(s.size()-k, s.size()) == rh2.get(0, k)) mx = max(mx, k);
              }
              
              if(rh.count(t)){
                /* dp[j][bit | (1 << j)]とdp[i][bit]の大きさを比較 */

                if(dp[j][bit | (1 << j)] == "~") dp[j][bit | (1 << j)] = dp[i][bit];
                else{ 
                  if(max(dp[j][bit | (1 << j)], dp[i][bit])){
                    dp[j][bit|(1<<j)] = dp[i][bit];
                  }
                }
              }else{
                string nx = s + t.substr(mx, t.size()-mx);
                /* dp[j][bit | (1 << j)]とnxの大きさを比較 */

                if(dp[j][bit | (1 << j)] == "~") dp[j][bit | (1 << j)] = nx;
                else{
                  if(max(dp[j][bit | (1 << j)], nx)){
                    dp[j][bit|(1<<j)] = nx;
                  }
                }
              }
            }
          }
        }
      }
    }
    string ans = "~";
    for(int i=0; i<n; i++){
      if(ans == "~") ans = dp[i][(1<<n)-1];
      else if(max(ans, dp[i][(1<<n)-1])){
        ans = dp[i][(1<<n)-1];
      }
    }
    cout << ans << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 470
memory_kb: 3516
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool contains(string a, string b){
    int n = a.length();
    int m = b.length();
    if(n < m) return false;
    for(int i=0; i<n-m+1; i++){
        if(b == a.substr(i, m)){
            return true;
        }
    }
    return false;
}
int match(string a, string b){
    int n = a.length();
    int m = b.length();
    for(int i=0; i<n; i++){
        if(m < n-i) continue;
        if(a.substr(i, n-i) == b.substr(0, n-i)){
            return n-i;
        }
    }
    return 0;
}

int main(){
    while(1){
        int n;
        cin >> n;
        if(n == 0) break;

        vector<string> s(n);
        for(int i=0; i<n; i++){
            cin >> s[i];
        }
        for(int i=n-1; i>=0; i--){
            for(int j=0; j<n; j++){
                if(i == j) continue;
                if(contains(s[j], s[i])){
                    s.erase(s.begin()+i);
                    n--;
                    break;
                }
            }
        }
        int sum = 0;
        for(auto str: s){
            sum += str.length();
        }
        vector<vector<int>> a(n, vector<int>(n));
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                a[i][j] = match(s[i], s[j]);
            }
        }
        vector<vector<string>> dp(1<<n, vector<string>(n, ""));
        for(int i=0; i<n; i++){
            dp[1<<i][i] = s[i];
        }
        for(int i=0; i<(1<<n); i++){
            for(int j=0; j<n; j++){
                if(!(i>>j&1)) continue;
                for(int k=0; k<n; k++){
                    if(i>>k&1) continue;
                    int ni = i | (1<<k);
                    string ns = dp[i][j] +s[k].substr(a[j][k], (int)s[k].length()-a[j][k]);
                    if(dp[ni][k] == "") dp[ni][k] = ns;
                    if(dp[ni][k] == "" or ns.length() < dp[ni][k].length() or
                            (ns.length() == dp[ni][k].length() and ns < dp[ni][k])){
                        dp[ni][k] = ns;
                    }
                }
            }
        }
        string ans(100, 'z');
        for(string str: dp.back()){
            if(str == "") continue;
            if(str.length() < ans.length() or (str.length()==ans.length() and str<ans)){
                ans = str;
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3440
final_rank: 1

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

bool contains(string str, string pre){
    int s = str.length(), p = pre.length();
    if(s < p)   return false;

    for(int i = 0; i <= s - p; i++){
        int j;
        for(j = 0; j < p; j++){ 
            if(str[i+j] != pre[j])  break;
        }
        if(j == p)  return true;
    }

    return false;
}

typedef unsigned long long ull;
ull x = 1000000007;

int f(string s, string t){
    int k = min(s.length(), t.length()), slen = s.length();
    int ret = 0;
    ull a = 0, b = 0, tmp = 1;
    for(int i = 1; i <= k; i++){
        a = a + s[slen-i]*tmp;
        b = b*x + t[i-1];
        if(a == b)  ret = i;
        tmp *= x;
    }
    return ret;
}

int main(){
    int n;
    while(cin >> n, n){
        vector<string> v;
        for(int i = 0; i < n; i++){
            string s;   cin >> s;
            v.push_back(s);
        }
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        n = v.size();
        vector<string> x;
        for(int i = 0; i < n; i++){
            bool valid = true;
            for(int j = 0; j < n; j++){
                if(i == j)  continue;
                if(contains(v[j], v[i]))    valid = false;
            }
            if(valid)   x.push_back(v[i]);
        }
        int n = x.size();
        vector<vector<string>> dp(n, vector<string>(1<<n, ""));
        for(int i = 0; i < n; i++)  dp[i][1<<i] = x[i];
        for(int s = 1; s < 1<<n; s++){
            for(int i = 0; i < n; i++){
                if(((s>>i)&1) == 0)    continue;
                for(int j = 0; j < n; j++){
                    if((s>>j)&1)    continue;
                    string tmp = dp[i][s];
                    tmp += x[j].substr(f(dp[i][s], x[j]));
                    int nbit = s + (1<<j);
                    if(dp[j][nbit] == "" || tmp.length() < dp[j][nbit].length() || (tmp.length()==dp[j][nbit].length() && tmp < dp[j][nbit])){
                        dp[j][nbit] = tmp;
                    }
                }
            }
        }
        string ans = dp[0].back();
        for(int i = 1; i < n; i++){
            if(ans.length() > dp[i].back().length() || (ans.length()==dp[i].back().length() && ans > dp[i].back())){
                ans = dp[i].back();
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3412
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) repi(i,0,n)
#define repi(i,a,b) for(int i=(int)(a);i < (int)(b);++i)
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class Key,class Value> ostream& operator << (ostream &s, map<Key,Value> M)
{ for ( auto itr = begin(M); itr != end(M); ++itr) { s << itr->first << ":" << itr->second; } return s;}
void print(const std::vector<int>& v)
{
  std::for_each(v.begin(), v.end(), [](int x) {
    std::cout << x << " ";
  });
  std::cout << std::endl;
}
bool is_sub(string s1,string s2) {
    int s1_size = s1.size();
    int s2_size = s2.size();
    if (s1_size > s2_size) {
        rep(i,s1_size-s2_size + 1) {
            bool flg = true;
            rep(j,s2_size) {
                if (s1[i+j] != s2[j]) {
                    flg = false;
                    break;
                }
            }
            if (flg) return true;
        }
        return false;
    }
    else {
        rep(i,s2_size-s1_size + 1) {
            bool flg = true;
            rep(j,s1_size) {
                if (s2[i+j] != s1[j]) {
                    flg = false;
                    break;
                }
            }
            if (flg) return true;
        }
        return false;
    }
}

int main() {
    while (true) {
        int n = 0;
        cin >> n;
        if (n == 0) {
            break;
        }
        long init = 0;
        vector<string> S(n);
        rep(i,n) cin >> S[i];
        rep(i,n-1) {
            repi(j,i+1,n) {
                // cout << is_sub(S[i],S[j]) << " " << i << " " << j << endl;
                if( is_sub(S[i],S[j]) ) {
                    if (S[i].size() > S[j].size()) init |= (1 << j);
                    else init |= (1 << i);
                }
            }
        }


        vector<int> v;
        rep(i,n) {
            if (!((init >> i) & 1)) v.push_back(i);
        }
        //cout << v << endl;
        // cout << v << endl;

        // suffix,prefix計算
        vector<vector<string>> preffix(n),suffix(n);
        rep(i,n) {
            if (((init >> i) & 1)) continue;
            preffix[i] = vector<string>(S[i].size()+1,"");
            suffix[i] = vector<string>(S[i].size()+1,"");
            rep(j, S[i].size()) {
                repi(k,j+1,S[i].size()+1) {
                    preffix[i][k] += S[i][j];
                    suffix[i][k] = S[i][S[i].size()-1-j] + suffix[i][k];
                }
            }
        }

        int string_num = v.size();
        string ans = "77";
        
        do {
            string cur = S[v[0]];
            rep(i, string_num-1) {
                int s_size = min(S[v[i]].size(),S[v[i+1]].size());
                rep(j,s_size) {
                    //cout << suffix[v[i]][s_size-1-j] << " " << preffix[v[i+1]][s_size-1-j] << endl;;
                    if (suffix[v[i]][s_size-1-j] == preffix[v[i+1]][s_size-1-j]) {
                        //cout << cur << " " << suffix[v[i+1]][S[v[i+1]].size()-j] << endl;
                        
                        int match = s_size - 1 - j;
                        cur += suffix[v[i+1]][S[v[i+1]].size()-match];
                        break;
                    }
                }
            }
            if (ans == "77" || ans.size() > cur.size() || ( ans.size() == cur.size() && ans > cur)) ans = cur;
        } while (next_permutation(v.begin(), v.end()));
        
        cout << ans << endl;


        

        
        
    }
}
accuracy: 1
time_ms: 4390
memory_kb: 3160
final_rank: 15

code_snippet: #include <bits/stdc++.h>

#define FOR(i,a,b) for(int i= (a); i<((int)b); ++i)
#define RFOR(i,a) for(int i=(a); i >= 0; --i)
#define FOE(i,a) for(auto i : a)
#define ALL(c) (c).begin(), (c).end()
#define RALL(c) (c).rbegin(), (c).rend()
#define DUMP(x)  cerr << #x << " = " << (x) << endl;
#define SUM(x) std::accumulate(ALL(x), 0LL)
#define MIN(v) *std::min_element(v.begin(), v.end())
#define MAX(v) *std::max_element(v.begin(), v.end())
#define EXIST(v,x) (std::find(v.begin(), v.end(), x) != v.end())
#define BIT_ON(bit, i) (bit & (1LL << i))

typedef long long LL;
template<typename T> using V = std::vector<T>;
template<typename T> using VV = std::vector<std::vector<T>>;
template<typename T> using VVV = std::vector<std::vector<std::vector<T>>>;
template<typename T> using VVVV = std::vector<std::vector<std::vector<std::vector<T>>>>;

template<class T> inline T ceil(T a, T b) { return (a + b - 1) / b; }
template<class T> inline void print(T x) { std::cout << x << std::endl; }
template<class T> inline void print_vec(const std::vector<T> &v) { for (int i = 0; i < v.size(); ++i) {  if (i != 0) {std::cout << " ";} std::cout << v[i];} std::cout << "\n"; }
template<class T> inline bool inside(T y, T x, T H, T W) {return 0 <= y and y < H and 0 <= x and x < W; }
template<class T> inline double euclidean_distance(T y1, T x1, T y2, T x2) { return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); }
template<class T> inline double manhattan_distance(T y1, T x1, T y2, T x2) { return abs(x1 - x2) + abs(y1 - y2); }
template<class T> inline std::vector<T> unique(std::vector<T> v) {
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    return v;
}

const int INF = 1 << 30;
const double EPS = 1e-9;
const std::string YES = "YES", Yes = "Yes", NO = "NO", No = "No";
const std::vector<int> dy4 = { 0, 1, 0, -1 }, dx4 = { 1, 0, -1, 0 };    // 4近傍（右, 下, 左, 上）
const std::vector<int> dy8 = { 0, -1, 0, 1, 1, -1, -1, 1 }, dx8 = { 1, 0, -1, 0, 1, 1, -1, -1 };

using namespace std;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    while (true) {
        int N;
        cin >> N;
        if (N == 0) {
            break;
        }

        V<string> tmp;
        FOR(i, 0, N) {
            string S;
            cin >> S;
            tmp.emplace_back(S);
        }

        tmp = unique(tmp);

        V<string> v;
        FOR(i, 0, tmp.size()) {
            string s = tmp[i];
            bool ok = true;

            FOR(j, 0, tmp.size()) {
                string t = tmp[j];
                if (i == j) {
                    continue;
                }

                if (t.find(s) != string::npos) {
                    ok = false;
                }
            }
            if (ok) {
                v.emplace_back(s);
            }
        }
        VV<string> memo(v.size(), V<string>(v.size(), ""));
        FOR(i, 0, v.size()) {
            string s = v[i];
            FOR(j, 0, v.size()) {
                string t = v[j];

                int same = 0;
                for (int n = v[j].size(); n >= 0; --n) {

                    bool ok = true;
                    FOR(k, 0, n) {
                        if (s[s.size() - n + k] != t[k]) {
                            ok = false;
                            break;
                        }
                    }
                    if (ok) {
                        same = n;
                        break;
                    }
                }
                string ans = "";
                FOR(k, same, t.size()) {
                    ans += t[k];
                }
                memo[i][j] = ans;
            }
        }

        string ans = "";
        FOR(i, 0, 110) {
            ans += "z";
        }

        V<int> idx(v.size());
        iota(ALL(idx), 0);

        do {
            string t = v[idx[0]];
            FOR(i, 1, v.size()) {
                t += memo[idx[i - 1]][idx[i]];
                if (t.size() > ans.size()) {
                    break;
                }
            }

            if (t.size() == ans.size()) {
                ans = min(ans, t);
            }
            else if (t.size() < ans.size()) {
                ans = t;
            }
        } while(next_permutation(ALL(idx)));

        print(ans);
    }

    return 0;
}
accuracy: 1
time_ms: 2000
memory_kb: 3192
final_rank: 13

code_snippet: #include <bits/stdc++.h>

#define FOR(i,a,b) for(int i= (a); i<((int)b); ++i)
#define RFOR(i,a) for(int i=(a); i >= 0; --i)
#define FOE(i,a) for(auto i : a)
#define ALL(c) (c).begin(), (c).end()
#define RALL(c) (c).rbegin(), (c).rend()
#define DUMP(x)  cerr << #x << " = " << (x) << endl;
#define SUM(x) std::accumulate(ALL(x), 0LL)
#define MIN(v) *std::min_element(v.begin(), v.end())
#define MAX(v) *std::max_element(v.begin(), v.end())
#define EXIST(v,x) (std::find(v.begin(), v.end(), x) != v.end())
#define BIT_ON(bit, i) (bit & (1LL << i))
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());

typedef long long LL;
template<typename T> using V = std::vector<T>;
template<typename T> using VV = std::vector<std::vector<T>>;
template<typename T> using VVV = std::vector<std::vector<std::vector<T>>>;
template<typename T> using VVVV = std::vector<std::vector<std::vector<std::vector<T>>>>;

template<class T> inline T ceil(T a, T b) { return (a + b - 1) / b; }
template<class T> inline void print(T x) { std::cout << x << std::endl; }
template<class T> inline void print_vec(const std::vector<T> &v) { for (int i = 0; i < v.size(); ++i) {  if (i != 0) {std::cout << " ";} std::cout << v[i];} std::cout << "\n"; }
template<class T> inline bool inside(T y, T x, T H, T W) {return 0 <= y and y < H and 0 <= x and x < W; }
template<class T> inline double euclidean_distance(T y1, T x1, T y2, T x2) { return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); }
template<class T> inline double manhattan_distance(T y1, T x1, T y2, T x2) { return abs(x1 - x2) + abs(y1 - y2); }

const int INF = 1 << 30;
const double EPS = 1e-9;
const std::string YES = "YES", Yes = "Yes", NO = "NO", No = "No";
const std::vector<int> dy4 = { 0, 1, 0, -1 }, dx4 = { 1, 0, -1, 0 };    // 4近傍（右, 下, 左, 上）
const std::vector<int> dy8 = { 0, -1, 0, 1, 1, -1, -1, 1 }, dx8 = { 1, 0, -1, 0, 1, 1, -1, -1 };

using namespace std;


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    while (true) {
        int N;
        cin >> N;
        if (N == 0) {
            break;
        }

        V<string> tmp;
        FOR(i, 0, N) {
            string S;
            cin >> S;
            tmp.emplace_back(S);
        }

        sort(ALL(tmp));
        tmp.erase(unique(ALL(tmp)), tmp.end());

        V<string> v;
        FOR(i, 0, tmp.size()) {
            string s = tmp[i];
            bool ok = true;

            FOR(j, 0, tmp.size()) {
                string t = tmp[j];
                if (i == j) {
                    continue;
                }

                if (t.find(s) != string::npos) {
                    ok = false;
                }
            }
            if (ok) {
                v.emplace_back(s);
            }
        }
        VV<string> memo(v.size(), V<string>(v.size(), ""));
        FOR(i, 0, v.size()) {
            string s = v[i];
            FOR(j, 0, v.size()) {
                string t = v[j];

                int same = 0;
                for (int n = v[j].size(); n >= 0; --n) {

                    bool ok = true;
                    FOR(k, 0, n) {
                        if (s[s.size() - n + k] != t[k]) {
                            ok = false;
                            break;
                        }
                    }
                    if (ok) {
                        same = n;
                        break;
                    }
                }
                string ans = "";
                FOR(k, same, t.size()) {
                    ans += t[k];
                }
                memo[i][j] = ans;
            }
        }

        string ans = "";
        FOR(i, 0, 110) {
            ans += "z";
        }

        V<int> idx(v.size());
        iota(ALL(idx), 0);

        do {
            string t = v[idx[0]];
            FOR(i, 1, v.size()) {
                t += memo[idx[i - 1]][idx[i]];
                if (t.size() > ans.size()) {
                    break;
                }
            }

            if (t.size() == ans.size()) {
                ans = min(ans, t);
            }
            else if (t.size() < ans.size()) {
                ans = t;
            }
        } while(next_permutation(ALL(idx)));

        print(ans);
    }

    return 0;
}
accuracy: 1
time_ms: 2020
memory_kb: 3188
final_rank: 14

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

struct Info{
	short state;
	short num_used,total_length;
	ll order;
};

int N,match_len[10][10],POW[12];
char first_words[10][11],words[10][11];

bool strCmp(char* base, char* comp){
	int length1,length2;
	for(length1=0;base[length1] != '\0';length1++);
	for(length2=0;comp[length2] != '\0';length2++);
	if(length1 != length2)return false;

	for(int i=0;base[i] != '\0'; i++){
		if(base[i] != comp[i])return false;
	}
	return true;
}

void strcpy(char* to,char* str){
	for(int i=0;str[i] != '\0';i++){
		to[i] = str[i];
		to[i+1] = '\0';
	}
}

int strCmp2(char* left,char* right){
	int i;

	if(strCmp(left,right))return 3;

	for(i=0;left[i] != '\0' && right[i] != '\0'; i++){
		if(left[i] != right[i]){
			if(left[i] < right[i])return 1;
			else{
				return 2;
			}
		}
	}
	if(left[i] == '\0')return 1;
	else{
		return 2;
	}
}

void func(){

	int words_index = 0,first_length[N],second_length[N];

	int tmp;

	for(int i = 0; i < N; i++){
		scanf("%s",first_words[i]);
		for(tmp = 0; first_words[i][tmp] != '\0';tmp++);
		first_length[i] = tmp;
	}

	int i_index,k_index,delete_num = 0;
	bool FLG;

	for(int i = 0; i < N; i++){

		FLG = true;

		for(int k = 0; k < N; k++){
			if(first_words[k][0] == '\0')continue;
			if(i != k && first_length[i] <= first_length[k]){

				for(int start = 0; start + first_length[i] <= first_length[k]; start++){

					for(i_index = 0,k_index = 0; i_index < first_length[i]
							&& first_words[i][i_index] == first_words[k][start+k_index]; i_index++,k_index++);

					if(i_index == first_length[i]){
						FLG = false;
						break;
					}
				}

			}
			if(!FLG)break;
		}

		if(FLG){
			second_length[words_index] = first_length[i];
			strcpy(words[words_index++],first_words[i]);
		}else{
			first_words[i][0] = '\0';
			delete_num++;
		}
	}

	N -= delete_num;

	int common,tmp_common;

	for(int left = 0;left < N; left++){
		for(int right = 0; right < N; right++){
			if(left != right){

				common = 0;

				for(int start = 0; start < second_length[left]; start++){
					for(tmp_common = 0; tmp_common < second_length[right] && start+tmp_common < second_length[left] &&
							words[left][start+tmp_common] == words[right][tmp_common]; tmp_common++);

					if(start+tmp_common == second_length[left]){
						common = tmp_common;
						break;
					}
				}

				match_len[left][right] = common;
			}
		}
	}

	queue<Info> Q;

	for(int i = 0; i < N; i++){
		Info new_info;
		new_info.state = POW[i];
		new_info.num_used = 1;
		new_info.order = i;
		new_info.total_length = second_length[i];
		Q.push(new_info);
	}

	int ans = BIG_NUM;

	char ans_word[101],tmp_word[101];
	int work[N];
	stack<int> S;

	while(!Q.empty()){

		if(Q.front().num_used == N){

			if(ans >= Q.front().total_length ){

				ll work_num = Q.front().order;
				for(int i = 0; i < N; i++){
					S.push(work_num%10);
					work_num /= 10;
				}

				for(int i = 0; i < N; i++){
					work[i] = S.top();
					S.pop();
				}

				strcpy(tmp_word,words[work[0]]);
				int index = second_length[work[0]];

				int pre = work[0];

				for(int i = 1; i < N; i++){
					for(int k = match_len[pre][work[i]];words[work[i]][k] != '\0'; k++){
						tmp_word[index++] = words[work[i]][k];
					}
					pre = work[i];
				}

				tmp_word[Q.front().total_length] = '\0';

				if(ans > Q.front().total_length){
					ans = Q.front().total_length;
					strcpy(ans_word,tmp_word);
				}else{
					if(strCmp2(ans_word,tmp_word) == 2){
						strcpy(ans_word,tmp_word);
					}
				}
			}
			Q.pop();
		}else if(Q.front().total_length >= ans){
			Q.pop();
		}else{

			for(int i = 0; i < N; i++){
				if(!(Q.front().state & (1 << i))){
					Info new_info;
					new_info.state = Q.front().state+POW[i];
					new_info.num_used = Q.front().num_used+1;
					new_info.order = 10*Q.front().order+i;
					new_info.total_length = Q.front().total_length+second_length[i]
								-match_len[Q.front().order%10][i];
					Q.push(new_info);
				}
			}
			Q.pop();
		}
	}

	printf("%s\n",ans_word);
}

int main() {

	for(int i = 0; i < 12; i++)POW[i] = pow(2,i);

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 520
memory_kb: 63124
final_rank: 20

code_snippet: #include<bits/stdc++.h>
#define r(i,n) for(int i=0;i<n;i++)
using namespace std;
vector<string>s;
int n;
string t,ans;
main(){
	while(cin>>n,n){
		set<string>ss;
		ans="zzzzzzzzzzzzzzzzzzzzzzzzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
		int p=0;
		vector<int>v;
		s.clear();
		r(i,n){
			cin>>t;
			if(!ss.count(t)){
				s.push_back(t);
				ss.insert(t);
			}
		}
		r(i,s.size())r(j,s.size())if(i!=j&&s[i].size()>=s[j].size()){
			r(k,s[i].size()){
				int sum=0;
				if(k+s[j].size()<=s[i].size()){
				for(int l=k;l-k<s[j].size();l++)
					if(s[i][l]==s[j][l-k])sum++;
				if(sum==s[j].size()){
					v.push_back(j);
					break;
				}
			}}
		}
		sort(v.begin(),v.end());
		v.erase(unique(v.begin(),v.end()),v.end());
		r(i,v.size()){
			s.erase(s.begin()+v[i]+p);
			p--;n--;
		}
		sort(s.begin(),s.end());
		do{
			t="";
			t+=s[0];
			for(int i=1;i<s.size();i++){
				int sum=0;
				for(int j=s[i-1].size()-1;j>=0;j--){
					int sum2=0,cnt=0;
					for(int k=0;;k++){
						if(k+j>=s[i-1].size())break;
						if(s[i][k]==s[i-1][j+k])sum2++;
						else goto L;
					}
					if(!cnt)sum=max(sum,sum2);L:;
				}
				t+=s[i].substr(sum);
			}
			if(ans.size()>t.size())ans=t;
			else if(ans.size()==t.size()) ans=min(ans,t);
		}while(next_permutation(s.begin(),s.end()));
		cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 6770
memory_kb: 3180
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

using pii = pair<int,int>;
using ll = long long;
#define rep(i, j) for(int i=0; i < (int)(j); i++)
#define repeat(i, j, k) for(int i = (j); i < (int)(k); i++)
#define all(v) v.begin(),v.end()
//#define debug(x) cerr << #x << " : " << x << endl
#define debug(...)

template<class T> bool set_min(T &a, const T &b) { return a > b  ? a = b, true : false; }
template<class T> bool set_max(T &a, const T &b) { return a < b  ? a = b, true : false; }
// vector
template<class T> istream& operator >> (istream &is , vector<T> &v) { for(T &a : v) is >> a; return is; }
template<class T> ostream& operator << (ostream &os , const vector<T> &v) { for(const T &t : v) os << "\t" << t; return os << endl; }
// pair
template<class T, class U> ostream& operator << (ostream &os , const pair<T, U> &v) { return os << "<" << v.first << ", " << v.second << ">"; }

const int INF = 1 << 30;
const ll INFL = 1LL << 60;


class Solver {
  public:
    int N;
    vector<string> S;
    bool contain(const string &s, const string &word) {
        rep(i, s.size()) {
            bool ok = true;
            rep(j, word.size()) {
                if(i + j >= s.size() or s[i + j] != word[j]) {
                    ok = false; break;
                }
            }
            if(ok) return true;
        }
        return false;
    }
    vector<string> merge(const string &s, const string &word) {
        vector<string> res;
        repeat(i, s.size() - word.size(), s.size())  {
            if(i < 0) continue;
            bool ok = true;
            rep(j, word.size()) if(i + j < s.size() and s[i + j] != word[j]) ok = false;
            if(ok) {
                int same = s.size() - i;
                res.emplace_back(s + word.substr(same));
            }
        }
        res.emplace_back(s + word);
        return res;
    }
    string calc(const string &s, int flg) {
        debug(s);
        string res;
        rep(i, N) if(not (flg & (1 << i))) {
            auto t = merge(s, S[i]);
            for(string &tt : t) {                
                string res2 = calc(tt, flg | (1 << i));
                if(res.size() == 0 or res2.size() < res.size()) res = res2;
                else if(res2.size() == res.size()) set_min(res, res2);
            }
        }
        if(res.size() > 0) return res;
        return s;
    }
            
    bool solve() {
        cin >> N;
        if(N == 0) return false;        
        S.resize(N); cin >> S;
        vector<string> T;
        rep(i, N) {
            bool ok =true;
            rep(j, N) if(i != j) {
                if(S[i] == S[j]) {
                    if(i > j) {
                        ok = false;
                        break;
                    }
                }
                else if(contain(S[j], S[i])) {
                    ok = false;
                    break;
                }                    
            }
            if(ok) T.push_back(S[i]);
        }
        debug(N); debug(S); debug(T);
        swap(S, T);
        N = S.size();
        cout << calc("", 0) << endl;
        return true;
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    while(Solver().solve());
    return 0;
}
accuracy: 1
time_ms: 7040
memory_kb: 3104
final_rank: 19

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <array>
#include <set>
#include <map>
#include <queue>
#include <tuple>
#include <unordered_set>
#include <unordered_map>
#include <functional>
#include <cassert>
#define repeat(i, n) for (int i = 0; (i) < int(n); ++(i))
#define repeat_from(i, m, n) for (int i = (m); (i) < int(n); ++(i))
#define repeat_reverse(i, n) for (int i = (n)-1; (i) >= 0; --(i))
#define repeat_from_reverse(i, m, n) for (int i = (n)-1; (i) >= int(m); --(i))
#define whole(f, x, ...) ([&](decltype((x)) whole) { return (f)(begin(whole), end(whole), ## __VA_ARGS__); })(x)
#define unittest_name_helper(counter) unittest_ ## counter
#define unittest_name(counter) unittest_name_helper(counter)
#define unittest __attribute__((constructor)) void unittest_name(__COUNTER__) ()
using ll = long long;
using namespace std;
template <class T> inline void setmax(T & a, T const & b) { a = max(a, b); }
template <class T> inline void setmin(T & a, T const & b) { a = min(a, b); }
template <typename X, typename T> auto vectors(X x, T a) { return vector<T>(x, a); }
template <typename X, typename Y, typename Z, typename... Zs> auto vectors(X x, Y y, Z z, Zs... zs) { auto cont = vectors(y, z, zs...); return vector<decltype(cont)>(x, cont); }

bool is_suffix(string const & a, string const & b) {
    if (a.length() > b.length()) return false;
    return b.compare(b.length() - a.length(), a.length(), a) == 0;
}
void setshort(string & a, string const & b) {
    if (a.empty() or b.length() < a.length() or (a.length() == b.length() and b < a)) {
        a = b;
    }
}

int main() {
assert (string("puyopuyo").find("yop") != string::npos);
assert (string("puyopuyo").find("pop") == string::npos);
assert (string("puyopuyo").find("aaa") == string::npos);
assert (string("puyo").find("puyopuyo") == string::npos);
    while (true) {
        // input
        int n; cin >> n;
        if (n == 0) break;
        vector<string> word(n); repeat (i, n) cin >> word[i];
        // solve
        vector<string> dp(1 << n);
        function<void (string const &, int)> go = [&](string const & s, int used) {
repeat (i, n) if (used & (1 << i)) {
assert (s.find(word[i]) != string::npos);
}
            repeat (i, n) if (not (used & (1 << i))) {
                if (s.find(word[i]) != string::npos) {
                    used |= 1 << i;
                }
            }
            setshort(dp[used], s);
            repeat (i, n) if (not (used & (1 << i))) {
                repeat_from (sep, 1, word[i].length()) {
                    if (is_suffix(word[i].substr(0, sep), s)) {
                        go(s + word[i].substr(sep), used | (1 << i));
                    }
                }
            }
        };
        repeat (i, n) {
            go(word[i], 1 << i);
        }
repeat (a, 1 << n) if (not dp[a].empty()) {
repeat (i, n) if (a & (1 << i)) {
assert (dp[a].find(word[i]) != string::npos);
}
}
// repeat (iteration, 3)
        repeat (a, 1 << n) if (not dp[a].empty()) {
            repeat (b, 1 << n) {
                if ((b | a) == a) {
                    setshort(dp[b], dp[a]);
                }
            }
        }
        repeat_from (a, 1, 1 << n) {
            assert (not dp[a].empty());
            repeat (b, 1 << n) if (not dp[b].empty()) {
                if (not (a & b)) {
                    setshort(dp[a | b], dp[a] + dp[b]);
                    setshort(dp[a | b], dp[b] + dp[a]);
                }
            }
        }
repeat (a, 1 << n) if (not dp[a].empty()) {
repeat (i, n) if (a & (1 << i)) {
assert (dp[a].find(word[i]) != string::npos);
}
}
        // output
repeat (i, n) {
assert (dp[(1 << n) - 1].find(word[i]) != string::npos);
}
        cout << dp[(1 << n) - 1] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 3100
final_rank: 3

code_snippet: #include<bits/stdc++.h>
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3f
#define EPS (1e-10)
#define rep(i,n)for(int i=0;i<n;i++)
using namespace std;
typedef long long ll;
typedef pair<int, int>P;

string s[10];
string dp[1 << 10][10];
int main() {
	int n;
	string inf; rep(i, 100)inf += 'z';
	while (scanf("%d", &n), n) {
		rep(i, n)cin >> s[i];
		rep(i, 1 << n)rep(j, n)dp[i][j] = inf;
		rep(i, n)dp[1 << i][i] = s[i];
		rep(i, 1 << n) {
			rep(j, n) {
				if (!(i >> j & 1))continue;
				if (dp[i][j] == inf)continue;
				rep(k, n) {
					if (i >> k & 1)continue;
					string t = dp[i | 1 << k][k];
					string p = dp[i][j];
					int d = s[k].size();
					while ((int)(p + s[k].substr(d)).find(s[k]) == -1)d--;
					p += s[k].substr(d);
					if (t.size() > p.size())dp[i | 1 << k][k] = p;
					else if (t.size() == p.size())dp[i | 1 << k][k] = min(dp[i | 1 << k][k], p);
				}
			}
		}
		string ans = inf;
		rep(i, n) {
			string t = dp[(1 << n) - 1][i];
			if (ans.size() > t.size())ans = t;
			else if (ans.size() == t.size())ans = min(ans, t);
		}
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 270
memory_kb: 3700
final_rank: 7

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
int x[14][14], n; string S[14];
string dp[14][16384];
bool erased[14]; vector<int>vec;
int SSS(string S, string T) {
	for (int i = min(S.size(), T.size()); i >= 0; i--) {
		if (S.substr(S.size() - i, i) == T.substr(0, i))return i;
	}
}
int main() {
	while (true) {
		cin >> n; vec.clear(); if (n == 0)break; for (int i = 0; i < n; i++)cin >> S[i];
		for (int i = 0; i < 14; i++) {
			erased[i] = false;
			for (int j = 0; j < 16384; j++) { dp[i][j] = "$"; }
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (S[i].size() > S[j].size()) {
					for (int k = 0; k <= S[i].size() - S[j].size(); k++) {
						if (S[i].substr(k, S[j].size()) == S[j])erased[j] = true;
					}
				}
			}
		}
		for (int i = 0; i < n; i++) { if (erased[i] == false)vec.push_back(i); }
		n = vec.size(); for (int i = 0; i < n; i++)S[i] = S[vec[i]];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (i != j)x[i][j] = SSS(S[i], S[j]);
			}
		}
		for (int i = 0; i < n; i++) { dp[i][(1 << i)] = S[i]; }
		for (int j = 0; j < (1 << n); j++) {
			for (int i = 0; i < n; i++) {
				if (dp[i][j] == "$")continue;
				int bit[14]; for (int k = 0; k < n; k++)bit[k] = (j / (1 << k)) % 2;
				for (int k = 0; k < n; k++) {
					if (bit[k] == 1)continue;
					string W1 = dp[i][j] + S[k].substr(x[i][k], S[k].size() - x[i][k]);
					if (dp[k][j + (1 << k)] == "$") { dp[k][j + (1 << k)] = W1; }
					if (dp[k][j + (1 << k)].size() > W1.size()) { dp[k][j + (1 << k)] = W1; }
					if (dp[k][j + (1 << k)].size() == W1.size() && dp[k][j + (1 << k)] > W1) { dp[k][j + (1 << k)] = W1; }
				}
			}
		}
		string minx = dp[0][(1 << n) - 1];
		for (int i = 0; i < n; i++) {
			if (minx.size() > dp[i][(1 << n) - 1].size()) { minx = dp[i][(1 << n) - 1]; }
			if (minx.size() == dp[i][(1 << n) - 1].size() && minx > dp[i][(1 << n) - 1]) { minx = dp[i][(1 << n) - 1]; }
		}
		cout << minx << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 280
memory_kb: 15836
final_rank: 12

code_snippet: #include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long ll;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define each(itr,c) for(__typeof(c.begin()) itr=c.begin(); itr!=c.end(); ++itr)
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second

typedef pair<int,int> pi;

int n;
vector<string> s,t;
int T;

const int INF=12345678;
int dp[15][1<<15];
pi par[15][1<<15];

// i,j???????????????????????±?????¨???????????????
int com[15][15];

string make_string(int now, int mask)
{
    pi p=par[now][mask];
    if(p.fi==-1) return t[now];
    return make_string(p.fi,p.se)+t[now].substr(com[p.fi][now]);
}

int main()
{
    cin.tie(0);ios::sync_with_stdio(false);

    while(cin >>n,n)
    {
        s=vector<string>(n);
        rep(i,n) cin >>s[i];

        vector<bool> use(n,true);
        rep(i,n)rep(j,n)
        {
            if(i==j) continue;

            int I=s[i].size(), J=s[j].size();
            if(I>J) continue;

            if(I==J)
            {
                if(s[i]==s[j] && i<j) use[i]=false;
            }
            else
            {
                rep(k,J-I+1)
                {
                    if(s[i]==s[j].substr(k,I))
                    {
                        // cout <<s[i]<<"   "<<s[j].substr(k,I)<<endl;
                        use[i]=false;
                    }
                }
            }
        }

        t.clear();
        rep(i,n) if(use[i]) t.pb(s[i]);
        T=t.size();
        // printf("T=%d\n", T);


        memset(com,0,sizeof(com));
        rep(i,T)rep(j,T)
        {
            if(i==j) continue;
            int I=t[i].size(), J=t[j].size();

            // cout <<i<<" "<<j<<endl;
            // cout <<t[i] << " "<<t[j]<<endl;
            rep(k,min(I,J))
            {
                int len=k+1;
                // cout <<"len= "<<len;
                // cout <<t[i].substr(I-len,len)<<" "<<t[j].substr(0,len)<<'\n';
                if(t[i].substr(I-len,len)==t[j].substr(0,len)) com[i][j]=len;
            }

        }

        fill(dp[0],dp[15],INF);

        // ??????
        rep(i,T)
        {
            dp[i][1<<i]=t[i].size();
            par[i][1<<i]=pi(-1,-1);
        }

        for(int mask=1; mask<(1<<T); ++mask)
        {
            rep(before,T)if(mask>>before&1)
            {
                rep(i,T)if(!(mask>>i&1))
                {
                    int add=t[i].size()-com[before][i];
                    if(dp[i][mask+(1<<i)]>dp[before][mask]+add)
                    {
                        dp[i][mask+(1<<i)]=dp[before][mask]+add;
                        par[i][mask+(1<<i)]=pi(before,mask);
                    }
                    else if(dp[i][mask+(1<<i)]==dp[before][mask]+add)
                    {
                        string old_s=make_string(i,mask+(1<<i));
                        string new_s=make_string(before,mask)+t[i].substr(com[before][i]);

                        if(new_s<old_s) par[i][mask+(1<<i)] = pi(before,mask);
                    }
                }
            }
        }

        int min_len=INF;
        rep(i,T)
        {
            // printf(" dp? %d\n", dp[i][(1<<T)-1]);
            min_len=min(min_len, dp[i][(1<<T)-1]);
        }
        string ans="#";
        rep(i,T)
        {
            if(dp[i][(1<<T)-1]==min_len)
            {
                if(ans=="#") ans=make_string(i,(1<<T)-1);
                else ans=min(ans,make_string(i,(1<<T)-1));
            }
        }

        // cout << "Scenario #" << sce+1 << '\n';
        cout << ans << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 5236
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

// does s contain t?
/*
bool contain(const string& s, const string& t)
{
  if(s.size() < t.size()) return false;
  int idx = 0;
  bool flag = false;
  for(int i = 0; i < t.size(); i++) {
    flag = false;
    for(int j = idx; j < s.size(); j++) {
      if(t[i] == s[j]) idx = j+1, flag = true;
      if(flag) break;
    }
    if(!flag) break;
  }
  return flag;
}
*/

bool cmp(const string& left, const string& right)
{
  if(left.size() != right.size()) return left.size() < right.size();
  for(int i = 0; i < left.size(); i++) {
    if(left[i] != right[i]) return left[i] < right[i];
  }
  return false;
}

// additional string to let s contain t.
/*
string addstr(const string& s, const string& t)
{
  int idx = 0;
  for(int i = 0; i < t.size(); i++) {
    bool flag = false;
    for(int j = idx; j < s.size(); j++) {
      if(t[i] == s[j]) idx = j+1, flag = true;
      if(flag) break;
    }
    if(!flag) return t.substr(i);
  }
  return "";
}
*/
string addstr(string s, string t)
{
  for(int i = 0; i < s.size(); i++) {
    if(s.substr(i) == t.substr(0, s.size()-i)) return t.substr(s.size()-i);
  }
  return t;
}

string inf()
{
  string ret = "";
  for(int i = 0; i < 1000; i++) ret += "~";
  return ret;
}

int main()
{
  int N;
  while(cin >> N, N) {
    vector<string> S(N);
    for(int i = 0; i < N; i++) cin >> S[i];
    sort(S.begin(), S.end(), cmp);
    S.erase(unique(S.begin(), S.end()), S.end());

    vector<string> T;
    for(int i = 0; i < S.size(); i++) {
      bool flag = false;
      for(int j = i+1; j < S.size(); j++) {
	if(S[j].find(S[i]) != string::npos) flag = true;
	if(flag) break;
      }
      if(!flag) T.push_back(S[i]);
    }
    
    int M = T.size();
    string add[11][11];
    for(int i = 0; i < M; i++) {
      for(int j = 0; j < M; j++) {
	add[i][j] = addstr(T[i], T[j]);
      }
    }
    
    string dp[1<<11][11];
    fill(dp[0], dp[1<<11], inf());
    for(int i = 0; i < M; i++) dp[1<<i][i] = T[i];
    
    string ans = inf();
    for(int i = 0; i < 1<<M; i++) {
      for(int j = 0; j < M; j++) {
	if(dp[i][j] == inf()) continue;
	if(i == (1<<M)-1) {
	  ans = min(ans, dp[i][j], cmp);
	}
	for(int k = 0; k < M; k++) {
	  if((i >> k) & 1) continue;
	  dp[i|(1<<k)][k] = min(dp[i|(1<<k)][k], dp[i][j] + add[j][k], cmp);
	}
      }
    }
    
    cout << ans << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 460
memory_kb: 3508
final_rank: 8

code_snippet: #include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int n; vector<string> s;
int main() {
	while (cin >> n, n) {
		s.resize(n);
		for (int i = 0; i < n; i++) cin >> s[i];
		vector<int> flag(n, 0); // bit / i -> j
		vector<vector<int> > cost(n, vector<int>(n)); // i -> j
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (s[i].find(s[j]) != string::npos) {
					flag[i] |= 1 << j;
				}
			}
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				for (int k = 0; k <= s[i].size(); k++) {
					string ret = s[i].substr(0, k) + s[j];
					if (ret.substr(0, s[i].size()) == s[i]) {
						cost[i][j] = ret.size() - s[i].size();
						break;
					}
				}
			}
		}
		vector<vector<string> > dp(1 << n, vector<string>(n, string(101, 'z')));
		dp[0][0] = "";
		for (int i = 1; i < 1 << n; i++) {
			for (int j = 0; j < n; j++) {
				if (!(i & (1 << j))) continue;
				int p = i - (1 << j);
				for (int k = 0; k < n; k++) {
					string con = (p != 0 ? s[j].substr(s[j].size() - cost[k][j], cost[k][j]) : s[j]);
					if (dp[i][j].size() > dp[p][k].size() + con.size()) dp[i][j] = dp[p][k] + con;
					else if (dp[i][j].size() == dp[p][k].size() + con.size() && dp[i][j] > dp[p][k] + con) dp[i][j] = dp[p][k] + con;
				}
			}
		}
		string ret(101, 'z');
		for (int i = 1; i < 1 << n; i++) {
			int bit = i;
			for (int j = 0; j < n; j++) {
				if (i & (1 << j)) bit |= flag[j];
			}
			if (bit == (1 << n) - 1) {
				for (int j = 0; j < n; j++) {
					if (ret.size() > dp[i][j].size()) ret = dp[i][j];
					else if (ret.size() == dp[i][j].size() && ret > dp[i][j]) ret = dp[i][j];
				}
			}
		}
		cout << ret << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3584
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define int long long   // <-----!!!!!!!!!!!!!!!!!!!

#define rep(i,n) for (int i=0;i<(n);i++)
#define rep2(i,a,b) for (int i=(a);i<(b);i++)
#define rrep(i,n) for (int i=(n)-1;i>=0;i--)
#define rrep2(i,a,b) for (int i=(a)-1;i>=b;i--)
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define printV(v) for(auto x : v){cout << x << " ";} cout << endl
#define printVS(vs) for(auto x : vs){cout << x << endl;}
#define printVV(vv) for(auto v : vv){for(auto&& x : v){cout << x << " ";}cout << endl;}
#define printP(p) cout << p.first << " " << p.second << endl
#define printVP(vp) for(auto p : vp) printP(p);

typedef long long ll;
typedef pair<int, int> Pii;
typedef tuple<int, int, int> TUPLE;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<Pii> vp;
typedef vector<vector<int>> Graph;
const int inf = 1e9;
const int mod = 1e9 + 7;

int n;
vector<string> s;
vvi d;
vvi dp;

int common(string s, string t) {
    for (int k = min(s.size(), t.size()); k >= 0; k--) {
        if (s.substr((int)s.size() - k) == t.substr(0, k)) {
            return k;
        }
    }
}

string concat(string s, string t) {
    int k = common(s, t);
    return s + t.substr(k);
}

string mymin(string s, string t) {
    if (s.size() < t.size()) return s;
    if (s.size() > t.size()) return t;
    return s < t ? s : t;
}

string dfs(int state, int j, string str) {
    if (__builtin_popcount(state) == 1) return concat(s[j], str);

    string ret(101, 'z');
    rep(i, n) {
        if (!((state >> i) & 1)) continue;
        if (dp[state - (1 << j)][i] + d[i][j] == dp[state][j]) {
            ret = mymin(ret, dfs(state - (1 << j), i, concat(s[i], str)));
        }
    }

    return ret;
}



signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    int t = 0;
    while (cin >> n, n) {
        s.clear();
        s.resize(n);
        rep(i, n) cin >> s[i];

        vector<bool> alive(n, true);
        rep(i, n) {
            rep2(j, i + 1, n) {
                if (s[i] == s[j]) {
                    alive[j] = false;
                }
            }
        }
        rep(i, n) {
            rep(j, n) {
                if (i == j) continue;
                if (s[i] != s[j] && s[i].find(s[j]) != string::npos) {
                    alive[j] = false;
                }
            }
        }

        {
            vector<string> t;
            rep(i, n) {
                if (alive[i]) {
                    t.emplace_back(s[i]);
                }
            }
            s = t;
            n = s.size();
        }

        d.clear();
        d.resize(n, vi(n));
        rep(i, n) {
            rep(j, n) {
                if (i == j) continue;
                d[i][j] = common(s[i], s[j]);
            }
        }

        dp.clear();
        dp.resize(1 << n, vi(n, -1));
        rep(i, n) {
            dp[1 << i][i] = 0;
        }
        rep(state, 1 << n) {
            rep(i, n) {
                if (dp[state][i] == -1) continue;
                rep(j, n) {
                    if ((state >> j) & 1) continue;
                    dp[state | (1 << j)][j] = max(dp[state | (1 << j)][j], dp[state][i] + d[i][j]);
                }
            }
        }

        int mx = *max_element(all(dp[(1 << n) - 1]));
        string ans(101, 'z');
        rep(j, n) {
            if (dp[(1 << n) - 1][j] == mx) {
                ans = mymin(ans, dfs((1 << n) - 1, j, s[j]));
            }
        }
        cout << ans << endl;
    }

}
accuracy: 1
time_ms: 890
memory_kb: 3272
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define int long long   // <-----!!!!!!!!!!!!!!!!!!!

#define rep(i,n) for (int i=0;i<(n);i++)
#define rep2(i,a,b) for (int i=(a);i<(b);i++)
#define rrep(i,n) for (int i=(n)-1;i>=0;i--)
#define rrep2(i,a,b) for (int i=(a)-1;i>=b;i--)
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define printV(v) for(auto x : v){cout << x << " ";} cout << endl
#define printVS(vs) for(auto x : vs){cout << x << endl;}
#define printVV(vv) for(auto v : vv){for(auto&& x : v){cout << x << " ";}cout << endl;}
#define printP(p) cout << p.first << " " << p.second << endl
#define printVP(vp) for(auto p : vp) printP(p);

typedef long long ll;
typedef pair<int, int> Pii;
typedef tuple<int, int, int> TUPLE;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<Pii> vp;
typedef vector<vector<int>> Graph;
const int inf = 1e9;
const int mod = 1e9 + 7;

int n;
vector<string> s(n);
vvi d(n, vi(n));
vvi dp(1 << n, vi(n, -1));

int common(string s, string t) {
    for (int k = min(s.size(), t.size()); k >= 0; k--) {
        if (s.substr((int)s.size() - k) == t.substr(0, k)) {
            return k;
        }
    }
}

string concat(string s, string t) {
    int k = common(s, t);
    return s + t.substr(k);
}

string mymin(string s, string t) {
    if (s.size() < t.size()) return s;
    if (s.size() > t.size()) return t;
    return s < t ? s : t;
}

string dfs(int state, int j, string str) {
    // cout << state << " " << j << " " << str << endl;
    // if (state == 0) return str;
    if (__builtin_popcount(state) == 1) return concat(s[j], str);

    string ret(101, 'z');
    rep(i, n) {
        if (!((state >> i) & 1)) continue;
        if (dp[state - (1 << j)][i] + d[i][j] == dp[state][j]) {
            ret = mymin(ret, dfs(state - (1 << j), i, concat(s[i], str)));
        }
    }

    return ret;
}



signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    int t = 0;
    while (cin >> n, n) {
        s.clear();
        s.resize(n);
        rep(i, n) cin >> s[i];

        // cout << t++ << endl;
        // printVS(s);

        vector<bool> alive(n, true);
        rep(i, n) {
            rep2(j, i + 1, n) {
                if (s[i] == s[j]) {
                    alive[j] = false;
                }
            }
        }
        rep(i, n) {
            rep(j, n) {
                if (i == j) continue;
                if (s[i] != s[j] && s[i].find(s[j]) != string::npos) {
                    alive[j] = false;
                }
            }
        }

        {
            vector<string> t;
            rep(i, n) {
                if (alive[i]) {
                    t.emplace_back(s[i]);
                }
            }
            s = t;
            n = s.size();
        }

        // cout << n << endl;
        // printVS(s);

        d.clear();
        d.resize(n, vi(n));
        rep(i, n) {
            rep(j, n) {
                if (i == j) continue;
                d[i][j] = common(s[i], s[j]);
            }
        }
        // printVV(d);
        // cout << endl;

        dp.clear();
        dp.resize(1 << n, vi(n, -1));
        rep(i, n) {
            dp[1 << i][i] = 0;
        }
        rep(state, 1 << n) {
            rep(i, n) {
                if (dp[state][i] == -1) continue;
                rep(j, n) {
                    if ((state >> j) & 1) continue;
                    dp[state | (1 << j)][j] = max(dp[state | (1 << j)][j], dp[state][i] + d[i][j]);
                }
            }
        }
        // printVV(dp);
        // cout << endl;

        int mx = *max_element(all(dp[(1 << n) - 1]));
        string ans(101, 'z');
        rep(j, n) {
            if (dp[(1 << n) - 1][j] == mx) {
                ans = mymin(ans, dfs((1 << n) - 1, j, s[j]));
            }
        }
        // cout << "* ans = " << ans << endl;
        cout << ans << endl;
    }

}
accuracy: 1
time_ms: 890
memory_kb: 3248
final_rank: 10