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 Ruby (judge verdict: Accepted)

def make_dup_length_array(word_list)
  dsize = word_list.length

  dup_length_array = Array.new(dsize){ Array.new(dsize, 0) }

  word_list.each_with_index{|word1, idx1|
    word_list.each_with_index{|word2, idx2|
      min_length = [word1.length, word2.length].min
      min_length.downto(0){|l|
        if word1[-l, l] == word2[0, l] && idx1 != idx2
          dup_length_array[idx1][idx2] = l
          break
        end
      }
    }
  }

  return dup_length_array
end

def concatinate_string_dict_order(word_list)
  word_list.sort.join
end

def generate_min_len_string(word_list, dup_len_array)
  is_zero_array = true

  # puts "enter: #{word_list}, #{dup_len_array}"

  dup_len_array.each_index{|idx1|
    dup_len_array[idx1].each_index{|idx2|
      l = dup_len_array[idx1][idx2]
      if l > 0
        # idx1 + idx2 ??????????????? idx2 ??????????????????
        # idx1 ?????????????????????
        new_word_list = word_list.dup
        new_word_list[idx2] = new_word_list[idx1] + word_list[idx2][l .. -1]
        new_word_list.delete_at(idx1)

        # [idx2][idx1] = 0
        # idx1 ???????????????
        # idx2 ????????? idx1??????????????????
        # idx1 ???????????????
        new_dup_len_array = dup_len_array.dup
        new_dup_len_array[idx2] = dup_len_array[idx2].dup
        new_dup_len_array[idx2][idx1] = 0
        new_dup_len_array.delete_at(idx1)
        tmp = new_dup_len_array.transpose
        tmp[idx2] = tmp[idx1].dup
        tmp.delete_at(idx1)
        new_dup_len_array = tmp.transpose

        is_zero_array = false
        generate_min_len_string(new_word_list, new_dup_len_array)
      end
    }
  }

  if is_zero_array
    sss = concatinate_string_dict_order(word_list)
    # puts "#{sss} #{$min_sss}"
    if sss.length < $min_sss.length ||
       (sss.length == $min_sss.length && sss < $min_sss)
      $min_sss = sss
    end
  end
end

loop{
  n = readline.to_i
  exit if n == 0

  word_list = []
  n.times{
    inp_word = readline.chomp
    word_list.each_with_index{|word, i|
      if word.include?(inp_word)
        inp_word = nil
        break
      end
      if inp_word.include?(word)
        word_list.delete(word)
      end
    }
    word_list << inp_word unless inp_word.nil?
  }

  $min_sss = word_list.join

  # p word_list
  dup_len_array = make_dup_length_array(word_list)
  # p dup_len_array

  generate_min_len_string(word_list, dup_len_array)

  puts $min_sss

  # $min_sss = word_list.join
  # (0..word_list.size-1).to_a.permutation{|order|
  #   cur_pos = order.shift
  #   sss = word_list[cur_pos]
  #   order.each{|cur_pos|
  #     next_word = word_list[cur_pos]

  #     min_length = [sss.length, next_word.length].min

  #     min_length.downto(0){|l|
  #       if sss[-l, l] == next_word[0, l]
  #         sss += next_word[l .. -1]
  #         break
  #       end
  #     }
  #   }
  #   # puts "cur:#{sss} min:#{min_sss}"
      
  #   if sss.length < min_sss.length ||
  #      (sss.length == min_sss.length && sss < min_sss)
  #     min_sss = sss
  #   end
  # }
  # puts min_sss
}