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: Wrong Answer)

#include <iostream>
#include <sstream>
#include <vector>
#include <list>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
using namespace std;

typedef vector <string> VS;

const int nsize = 11;
int C[nsize][nsize];
string dp[nsize][1<<nsize];
const string inf = string( nsize * nsize, 'Z' );

bool include( string a, string b ) {
    // true: a has b
    if ( a.size() < b.size() ) return false;
    int as = a.size();
    int bs = b.size();
    for ( int i = 0; i + bs - 1 < as; ++ i ) {
        if ( a.substr( i, bs ) == b ) return true;
    }
    return false;
}

VS convert( VS S ) {
    VS T;
    int n = S.size();
    for ( int i = 0; i < n; ++ i ) {
        bool flag = true;
        for ( int j = 0; j < n; ++ j ) {
            if ( i == j ) continue;
            if ( include( S[j], S[i] ) ) flag = false;
        }
        if ( flag ) {
            T.push_back( S[i] );
        }
    }
    return T;
}

int calc( string a, string b ) {
    int answer = 0;
    int n = min( a.size(), b.size() );
    reverse( a.begin(), a.end() );
    for ( int i = 0; i <= n; ++ i ) {
        string s = a.substr( 0, i );
        reverse( s.begin(), s.end() );
        if ( s == b.substr( 0, i ) ) {
            answer = max( answer, i );
        }
    }
    return answer;
}

string get_sub( string s, int c ) {
    return s.substr( c );
}

string min_str( string a, string b ) {
    if ( a.size() == b.size() ) {
        return a < b ? a : b;
    } else {
        return a.size() < b.size() ? a : b;
    }
}

bool check( string a, string b ) {
    if ( a.size() == b.size() ) {
        return a >= b;
    } else {
        return a.size() >= b.size();
    }
}

string min_element_str( VS W ) {
    int n = W.size();
    for ( int i = 0; i + 1 < n; ++ i ) {
        for ( int j = i + 1; j < n; ++ j ) {
            if ( check( W[i], W[j] ) ) {
                swap( W[i], W[j] );
            }
        }
    }
    return W[0];
}

int main() {
    int n;
    while ( cin >> n && n ) {
        VS W;
        string w;
        for ( int i = 0; i < n; ++ i ) {
            cin >> w;
            W.push_back( w );
        }

        W = convert( W );
        n = W.size();
        for ( int i = 0; i < n; ++ i ) {
            for ( int j = 0; j < n; ++ j ) {
                C[i][j] = calc( W[i], W[j] );
            }
        }

        int m = 1 << n;
        for ( int i = 0; i < n; ++ i ) {
            for ( int j = 0; j < m; ++ j ) {
                dp[i][j] = inf;
            }
        }
        for ( int i = 0; i < n; ++ i ) {
            dp[i][1<<i] = W[i];
        }
        for ( int i = 0; i < m; ++ i ) { // state
            for ( int j = 0; j < n; ++ j ) { // prev
                if ( dp[j][i] == inf ) continue;
                for ( int k = 0; k < n; ++ k ) { // next
                    if ( i & 1 << k ) continue;
                    int s = i;
                    int ns = i | 1 << k;
                    dp[k][ns] = min_str( dp[k][ns], dp[j][s] + get_sub( W[k], C[j][k] ) );
                }
            }
        }
        string answer = inf;
        for ( int i = 0; i < n; ++ i ) {
            answer = min_str( answer, dp[i][m-1] );
        }
        cout << answer << endl;
    }
    return 0;
}