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)

/*
  AOJ 2022
 */
#include <stdio.h>
#include <string.h>

int N;
int num[10];
int frag[10];
char words[11][11];
char result[101];
char shortest[1001];

extern void strcat_erase_common(char *,char *);
void update_shortest(char * r)
{
  if(shortest[0]=='\0' || (strlen(shortest)>strlen(r))
     || ((strlen(shortest)==strlen(r)) && 0>strcmp(shortest,r)))
    {
      strcpy(shortest,r);
    }
}
void strcat_order(int * order)
{
  int i;

  memset(&result[0],'\0',11);
  strcpy(&result[0],&words[order[N]][0]);
  for(i=1;i<N;i++)
    strcat_erase_common(result,&words[order[N-i]][0]);

}

void strcat_erase_common(char * buf,char *add)
{
  int i,len;

  if(strstr(buf,add))
    return;

  len=strlen(buf);
  for(i=strlen(add)-1;i>0;i--)
    if(0==strncmp(buf+len-i,add,i))
      {
      strcat(buf,add+i);
      return;
      }
  strcat(buf,add);
  return;
}

void fx(int n,int k)
{
  int i,f,j;
  for(i=0;i<n;++i)
    {
      f=frag[i];
      if(f == 0)
	{
	  frag[i]=1;
	  num[k] = i+1;
	  if(k==1)
	    {
	      strcat_order(num);
	      update_shortest(result);
	    }
	  else
	    {
	      fx(n,k-1);
	    }
	  frag[i] = 0;
	}
    }
}

int main()
{
int i,k;


 while(EOF!=scanf("%d",&N) && N)
   {
     memset(num,0,N*sizeof(int));
     memset(frag,0,N*sizeof(int));

     for(i=1;i<=N;i++)
       scanf("%s ",&(words[i][0]));
#ifdef DEBUG2
  for(i=1;i<=N;i++)
    printf("%s:",&words[i][0]);
  printf("\n");
#endif
     memset(shortest,'\0',1000);

     fx(N,N);
     printf("%s\n",shortest);
   }
 return(0);
}