Problem:
Problem C: Palindrome

Problem

太郎君はそれぞれの長さがLの文字列をN個持っている。太郎君は回文が大好きなので、N個のうちいくつかの文字列を選んで好きな順番に並べることで、できるだけ長い回文を作りたい。

太郎君が作ることのできる回文の中で、最長のものを求めよ。複数ある場合は、そのうち辞書順で最小のものを出力せよ。どのように選んで並べても回文が作れない場合は、空行を出力せよ。

Input

入力は以下の形式で与えられる。

N L
s1
s2
.
.
.
sN

1行目に、文字列の数Nと文字列の長さLが与えられる。続く2行目からN + 1行目に太郎君が持っている文字列s_iが与えられる。

Constraints

入力は以下の条件を満たす。

1 ≤ N ≤ 1000

1 ≤ L ≤ 30

s_iは英小文字からなる文字列である。

Output

最長の回文の中で辞書順最小のものを出力せよ。回文が作れない場合は空行を出力せよ。

Sample Input 1

4 2
oi
io
rr
rr

Sample Output 1

iorrrroi

Sample Input 2

5 1
a
b
c
a
c

Sample Output 2

acbca

Sample Input 3

3 3
uki
uku
uke

Sample Output 3

uku

Solution in C# (judge verdict: Accepted)

using System.Text;
using System.Collections.Generic;
using System.Linq;
using System;

public class Hello
{
    public static void Main()
    {
        string[] line = Console.ReadLine().Trim().Split(' ');
        var n = int.Parse(line[0]);
        var L = int.Parse(line[1]);
        var a = new string[n];
        for (int i = 0; i < n; i++) a[i] = Console.ReadLine().Trim();
        var used = new bool[n];
        var ans1 = getAns1(a, n, used);
        var ans = getAns2(a, used, ans1, n);
        Console.WriteLine(ans);
    }
    static bool check(string s)
    {
        var imax = s.Length / 2;
        for (int i = 0; i < imax; i++)
            if (s[i] != s[s.Length - 1 - i]) return false;
        return true;
    }
    static string getAns2(string[] a, bool[] used, List<string> ans1, int n)
    {
        var ans2 = new List<string>();
        for (int i = 0; i < n; i++)
            if (!used[i] && check(a[i])) ans2.Add(a[i]);
        ans2.Sort();
        var sb = new StringBuilder();
        for (int i = 0; i < ans1.Count(); i++) sb.Append(ans1[i]);
        var ans3 = sb.ToString();
        var ans4 = getRev(ans3);
        if (ans2.Count() > 0) return ans3 + ans2[0] + ans4;
        else return ans3 + ans4;
    }
    static string getRev(string s)
    {
        var a = s.ToCharArray();
        Array.Reverse(a);
        return new string(a);
    }
    static List<string> getAns1(string[] a, int n, bool[] used)
    {
        var ans1 = new List<string>();
        for (int i = 0; i < n; i++)
            if (!used[i])
            {
                var w = getRev(a[i]);
                for (int j = i + 1; j < n; j++)
                    if (!used[j] && w == a[j])
                    {
                        var t = a[i].CompareTo(w);
                        if (t <= 0) ans1.Add(a[i]);
                        else ans1.Add(w);
                        used[i] = true;
                        used[j] = true;
                        break;
                    }
            }
        ans1.Sort();
        return ans1;
    }
}