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<stdio.h>
#include<string.h>

#define MAX 11
#define S_MAX 101

int InsideCommon( const char *a, const char *b ){
	if( strstr( a, b ) )
		return 1;
	else
		return 0;
}

void Overlap( const char *a, const char *b, char * ret ){
	unsigned int i, j, len = 0;
	unsigned int alen = strlen(a);
	unsigned int blen = strlen(b);
	unsigned int min_len = alen < blen ? alen : blen;
	
	for(i = min_len; i >= 1; --i){
		int bOk = 1;
		for(j = 0; j < i; ++j){
			if( a[ alen - i + j ] != b[ j ] ){
				bOk = 0;
			}
		}
		if( bOk ){
			len = i;
			break;
		}
	}
	strcpy( ret, a );
	strcat( ret, b + len );
}

int invest;

int strless( const char *a, const char *b ){
	if( strlen( a ) < strlen( b ) )
		return 1;
	else if( strlen( a ) == strlen( b ) && strcmp( a, b ) <= 0 )
		return 0;
	else
		return 0;
}

void solve(int n, const char strs[MAX-1][MAX], int *bUsed, char *now, char *ans){
	int i;
	int bAllUsed = 1;

	for(i = 0; i < n; ++i){
		if( !bUsed[i] ){
			char t[S_MAX]="";
			bAllUsed = 0;
			
			strcpy(t,now);

			if( InsideCommon( t, strs[i] ) ){
				bUsed[i] = 1;
				solve( n, strs, bUsed, t, ans );
				bUsed[i] = 0;
				continue;
			}
			if( InsideCommon( strs[i], t ) ){
				strcpy( t, strs[i] );
				bUsed[i] = 1;
				solve( n, strs, bUsed, t, ans );
				bUsed[i] = 0;
				continue;
			}

			Overlap( now, strs[i], t );
			bUsed[i] = 1;
			if( strless( t, ans ) )
				solve( n, strs, bUsed, t, ans );
			bUsed[i] = 0;
		}
	}
	
	if( bAllUsed ){
		if( strless( now, ans ) )
			strcpy( ans, now );
	}
}

int main(){
	while(1){
		int i,j,n;
		char now[S_MAX]="";
		char ans[S_MAX]="";
		char strs[MAX-1][MAX]={{"",},};
		int bUsed[MAX-1]={0,};

		scanf("%d", &n);
		if(n == 0)break;

		for(i = 0; i < n; ++i){
			int bSkip = 0;
			scanf("%s", strs[i]);
			
			for(j = 0; j < i; ++j){
				if( InsideCommon( strs[j], strs[i] ) ){
					bSkip = 1;
					break;
				}
			}
			
			if( bSkip ){
				--n;
				--i;
				continue;
			}
			strcat(ans,strs[i]);
		}

		invest = 0;
		//printf("N: %d BEST STATE: %s\n", n, ans);
		solve( n, strs, bUsed, now, ans );
		
		printf("%s\n", ans);
	}
}