Problem:
Score : 200 points

Problem Statement

Iroha has a sequence of N strings S_1, S_2, ..., S_N. The length of each string is L.

She will concatenate all of the strings in some order, to produce a long string.

Among all strings that she can produce in this way, find the lexicographically smallest one.

Here, a string s=s_1s_2s_3...s_n is lexicographically smaller than another string t=t_1t_2t_3...t_m if and only if one of the following holds:

There exists an index i(1≦i≦min(n,m)), such that s_j = t_j for all indices j(1≦j<i), and s_i<t_i.

s_i = t_i for all integers i(1≦i≦min(n,m)), and n<m.

Constraints

1 ≦ N, L ≦ 100

For each i, the length of S_i equals L.

For each i, S_i consists of lowercase letters.

Input

The input is given from Standard Input in the following format:

N L
S_1
S_2
:
S_N

Output

Print the lexicographically smallest string that Iroha can produce.

Sample Input 1

3 3
dxx
axx
cxx

Sample Output 1

axxcxxdxx

The following order should be used: axx, cxx, dxx.

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

class inputFile
{
	//変数
	bool b_testMode;
	List<string> list_s_line;
	int i_index;

	//コンストラクタ
	public inputFile()
	{
		//変数初期化
		b_testMode = false;
		list_s_line = new List<string>();
		i_index = 0;

		//ファイル読み込み
		read_file();
	}

	//ファイル読み込み
	void read_file()
	{
		//テストモードの場合のみ
		if (b_testMode == true)
		{
			// StreamReader の新しいインスタンスを生成する
			System.IO.StreamReader cReader =
				new System.IO.StreamReader(@"C:\000\VisualStudio-workspace\paiza\inputFile.txt", Encoding.Default);

			// 読み込みできる文字がなくなるまで繰り返す
			while (cReader.Peek() >= 0)
			{
				// ファイルを 1 行ずつ読み込む
				string s_temp = cReader.ReadLine();
				// 読み込んだものを追加で格納する
				list_s_line.Add(s_temp);
			}

			// cReader を閉じる (正しくは オブジェクトの破棄を保証する を参照)
			cReader.Close();
		}
	}

	//1行ずつ取得
	public string get()
	{
		//テストモードの場合
		if (b_testMode == true)
		{
			if (i_index >= list_s_line.Count)
			{
				return "";
			}

			return list_s_line[i_index++];
		}
		//本番モードの場合
		else
		{
			string s_temp = Console.ReadLine();
			if(s_temp == null || s_temp == "")
			{
				return "";
			}
			else
			{
				return s_temp;
			}
		}
	}
}

class Program
{
	//クラス変数
	static inputFile input;

	//Main
	static void Main(string[] args)
	{
		//ファイル読み込み
		input = new inputFile();

		//データ作成
		PRM = new Param();
		make_data();

		//メインロジック
		main_logic();
	}

	//データ作成
	static Param PRM;
	class Param
	{
		//==================================================
		//長さ L の文字列
		public int cl_i_string_length { set; get; }
		//文字列を N 個
		public int cl_i_string_cnt { set; get; }
		//文字列リスト
		public List<MOJIRETU> cl_list_MOJIRETU { set; get; }
		//==================================================
		public Param()
		{
			string[] a_s;
			//==================================================
			a_s = input.get().Split(' ');
			cl_i_string_length = int.Parse(a_s[0]);
			cl_i_string_cnt = int.Parse(a_s[1]);
			//------------------------------------------------------------
			cl_list_MOJIRETU = new List<MOJIRETU>();
			for(int aaa=1; aaa<=cl_i_string_cnt; aaa++)
			{
				MOJIRETU s = new MOJIRETU(input.get());
				cl_list_MOJIRETU.Add(s);
			}
			//==================================================
		}
	}
	//==================================================
	class MOJI
	{
		public int cl_i_string_no { set; get; }
		public int cl_i_moji_keta { set; get; }
		public char cl_c_moji { set; get; }
		public int cl_i_moji { set; get; }
		public int cl_i_moji_order { set; get; }
	}

	class MOJIRETU
	{
		static int cls_string_no_counter = 1;
		public int cl_i_string_no { set; get; }
		public string cl_s_string { set; get; }
		public int cl_i_order { set; get; }
		public bool cl_b_orderSet_complete { set; get; }
		public List<MOJI> cl_list_MOJI { set; get; }
		public MOJIRETU(string in_s)
		{
			//クラス変数セット
			cl_i_string_no = cls_string_no_counter++;
			cl_s_string = in_s;
			cl_b_orderSet_complete = false;
			//リスト作成
			cl_list_MOJI = new List<MOJI>();

			//list_MOJI作成
			make_list_MOJI();
		}

		//文字別char番号セット
		void make_list_MOJI()
		{
			//文字列配列化
			char[] a_c = cl_s_string.ToCharArray();
			//文字別char番号セット
			for (int aaa = 1; aaa <= a_c.Length; aaa++)
			{
				MOJI m = new MOJI();
				m.cl_i_string_no = cl_i_string_no;
				m.cl_i_moji_keta = aaa;
				m.cl_c_moji = a_c[aaa - 1];
				m.cl_i_moji = (int)a_c[aaa - 1];
				cl_list_MOJI.Add(m);
			}
		}

	}
	//==================================================

	static void make_data()
	{
		//==================================================
		//MOJI_order作成
		make_MOJI_order();

		//MOJIRETU_order作成
		make_MOJIRETU_order();
		//==================================================
	}
	//==================================================
	//MOJIRETU_order作成
	static void make_MOJIRETU_order()
	{
		//各文字列各桁ループ(昇順)
		for (int aaa = 1; aaa <= PRM.cl_i_string_length; aaa++)
		{
			//すべてオーダー決定していたら終了
			if (PRM.cl_list_MOJIRETU.FindAll(bbb => bbb.cl_b_orderSet_complete == false).Count == 0)
			{
				break;
			}

			//MOJIリスト作成(完了フラグOFFのみ)
			List<MOJI> list_MOJI_work = new List<MOJI>();
			foreach (MOJIRETU in_MOJIRETU in PRM.cl_list_MOJIRETU.FindAll(bbb => bbb.cl_b_orderSet_complete == false))
			{
				list_MOJI_work.Add(in_MOJIRETU.cl_list_MOJI[aaa - 1]);
			}

			//char番号順ソート(昇順)
			list_MOJI_work.Sort((a, b) => a.cl_i_moji - b.cl_i_moji);

			//orderセット
			int i_order = 0;
			int i_pre_char = -999;
			foreach (MOJI in_MOJI in list_MOJI_work)
			{
				//セット対象MOJIRETU
				MOJIRETU MOJIRETU_work = PRM.cl_list_MOJIRETU.Find(ccc => ccc.cl_i_string_no == in_MOJI.cl_i_string_no);

				//違う文字だった場合
				if (in_MOJI.cl_i_moji != i_pre_char)
				{
					//オーダーセット
					MOJIRETU_work.cl_i_order = ++i_order;
					//プレcharセット
					i_pre_char = in_MOJI.cl_i_moji;
				}
				//同じ文字だった場合
				else
				{
					//同じオーダーをセット
					MOJIRETU_work.cl_i_order = i_order;
				}
			}

			//orderSet_completeフラグセット
			//orderループ
			for (int bbb = 1; bbb <= PRM.cl_i_string_cnt; bbb++)
			{
				//文字列抽出
				List<MOJIRETU> list_MOJIRETU_temp = PRM.cl_list_MOJIRETU.FindAll(ccc => ccc.cl_i_order == bbb);
				//対象件数が複数件なら
				if (list_MOJIRETU_temp.Count >= 2)
				{
					//以降はフラグセットしない
					break;
				}
				//対象件数が1件なら
				if (list_MOJIRETU_temp.Count == 1)
				{
					//フラグセット
					list_MOJIRETU_temp[0].cl_b_orderSet_complete = true;
				}
			}
		}
	}

	//MOJI_order作成
	static void make_MOJI_order()
	{
		//各文字列各桁ループ(降順)
		for (int aaa = 1; aaa <= PRM.cl_i_string_length; aaa++)
		{
			//MOJIリスト作成
			List<MOJI> list_MOJI_work = new List<MOJI>();
			foreach (MOJIRETU in_MOJIRETU in PRM.cl_list_MOJIRETU)
			{
				list_MOJI_work.Add(in_MOJIRETU.cl_list_MOJI[aaa - 1]);
			}

			//char番号順ソート(昇順)
			list_MOJI_work.Sort((a, b) => a.cl_i_moji - b.cl_i_moji);

			//char番号順オーダー設定
			int i_order = 0;
			int i_pre_char = -999;
			foreach (MOJI in_MOJI in list_MOJI_work)
			{
				//違う文字だった場合
				if (in_MOJI.cl_i_moji != i_pre_char)
				{
					//プラス1セット
					in_MOJI.cl_i_moji_order = ++i_order;
					i_pre_char = in_MOJI.cl_i_moji;
				}
				//同じ文字だった場合
				else
				{
					//同じオーダーをセット
					in_MOJI.cl_i_moji_order = i_order;
				}
			}
		}
	}

	//==================================================
	//メインロジック
	static void main_logic()
	{
		//==================================================
		//出力
		//与えられる文字列を好きな順番で全て結合してできる文字列のうち、もっとも辞書順で小さいものを出力せよ。

		//order昇順ソート
		PRM.cl_list_MOJIRETU.Sort((aa, bb) => aa.cl_i_order - bb.cl_i_order);
		int a =0;

		//出力
		foreach(MOJIRETU in_MOJIRETU in PRM.cl_list_MOJIRETU)
		{
			Console.Write(in_MOJIRETU.cl_s_string);
		}
		Console.WriteLine("");
		//==================================================
	}

}