#include<iostream>
#include<vector>
#include<string.h>
#include<math.h>
#include<iomanip>
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mk(u, v) make_pair((u), (v))
#define pb(element) push_back((element))
#define loop(from, to, counter) for(int counter = from; counter < to; ++counter)
#define loopi(n) for(int i = 0; i < n; ++i)
#define loopj(n) for(int j = 0; j < n; ++j)
#define loopk(n) for(int k = 0; k < n; ++k)
#define F first
#define S second
#define LL_MAX 0x7FFFFFFFFFFFFFFF
#define searchSet(st, v) (st.find(v) != st.end())




/** Geometry **/
typedef complex<double> point;
#define EPS 1e-9
#define OO 1e9
#define X real()
#define Y imag()
#define vec(a,b) ((b) - (a))
#define polar(r,t) ((r) * exp(point(0, (t))))
#define angle(v) (atan2((v).Y, (v).X))
#define length(v) ((double)hypot((v).Y, (v).X))



inline void intialize()
{
    cin.tie(0);
    ios_base::sync_with_stdio(0);
    cout.tie(0);
}

void dealWithFiles(bool read, bool write, const char inFileName[], const char outFileName[])
{
    if(read)
        freopen (inFileName, "r",stdin);
    if(write)
        freopen (outFileName,"w",stdout);
}

int dcmp(double a, double b)
{
    if(abs(a - b) <= EPS)
        return 0;
    if(a > b)
        return -1;
    else
        return 1;
}

/* ______________________________________________________ */

const int oo = 0x3F3F3F3F, modulo = 1000000007;
const double PI = acos(-1);

//const int N = 55, M = 55;
//
//int n, m, ii, jj, cnt;
//int ne, head[N], nxt[M], to[M], IN[N];
//
//void init(){
//    memset(head, -1, sizeof head);
//    ne = 0;
//}
//
//void addEdge(int f, int t){
//    to[ne] = t;
//    nxt[ne] = head[f];
//    IN[t]++;
//    head[f] = ne++;
//}
//
//void addBiEdge(int a, int b){
//    addEdge(a, b);
//    addEdge(b, a);
//}

const int N = 100;
string arr[N];

int main()
{
//    dealWithFiles(1, 1, "in.txt", "output.txt");
//    intialize();

    int n, l;
    cin >> n >> l;
    loopi(n)
        cin >> arr[i];

    sort(arr, arr + n);
    loopi(n)
        cout << arr[i];
    cout << endl;
}


vector<int> splitString(string s)
{
    int n = s.size();
    vector<int> v;
    for(int i = 0; i < n; ++i)
    {
        int temp = 0;
        while(s[i] != ' ' && i < n)
        {
            temp = (temp * 10) + (s[i] - '0');
            i++;
        }
        v.push_back(temp);
    }
    return v;
}









/* ******************************************************************************************************************************** */
//
//ll fastPower(ll b, ll p, ll mod = LLONG_MAX){
//    ll ans = 1;
//    while(p){
//        if(p & 1)
//            ans *= b;
//        p >>= 1;
//        b *= b;
//        while(b > mod)  b -= mod;
//        while(ans > mod)  ans -= mod;
//    }
//    return ans;
//}
//
//bool cmp(pair<int, string> u, pair<int, string> v)
//{
//    if(u.F > v.F)
//        return 1;
//    if(u.F < v.F)
//        return 0;
//    string s1 = u.S, s2 = v.S;
//    int ss1 = s1.size(), ss2 = s2.size();
//    int i = 0;
//    while(s1[i] == s2[i] && s1[i] && s2[i]) i++;
//    if(s1[i] <= s2[i])
//        return 1;
//    else
//        return 0;
//}
//
//inline void intialize()
//{
//    cin.tie(0);
//    ios_base::sync_with_stdio(0);
//    cout.tie(0);
//}
//
//void dealWithFiles(bool read, bool write, const char inFileName[], const char outFileName[])
//{
//    if(read)
//        freopen (inFileName, "r",stdin);
//    if(write)
//        freopen (outFileName,"w",stdout);
//}
//
///* ******************************************************************************************************************************** */
//
//long long sumFromOnetoN(long long n)
//{
//    return n * (n + 1) / 2;
//}
///*
// * long long fastPower(long long b, long long p, long long modulo = -1)
// * {
// *     if(!p)
// *         return 1;
// *     long long res = fastPower(b,p >>1);
// *     res *= res;
// *     if(~modulo)
// *         res %= modulo;
// *     if(p & 1)
// *         res *= b;
// *     if(~modulo)
// *         res %= modulo;
// *     return res;
// * }
// */
//
//long long sumPowers(long long a, int k)
//{
//    // Returns (a^1 + a^2 + a^3 + a^4 + a^5 + a^6 + ......... + a^k ) in O(n);
//
//    if(k == 0)
//        return 0;
//    if(k & 1)
//        return a * (1 + sumPowers(a, k - 1));
//
//    long long half = sumPowers(a, k / 2);
//    return half * (1 + half - sumPowers(a, (k / 2) - 1));
//
//}
//
//long long factorial(int n)
//{
//    /* Be aware of Expected OVERFLOW */
//    long long ans = 1;
//    for(int i = 2; i <= n; ++i)
//        ans = (ans * i) /* %  modulo */ ;
//    return ans;
//}
//
//long long permutations(long long n, long long k)
//{
//    return factorial(n) / factorial(n - k);
//}
//
//long long combinations(long long n, long long k)
//{
//    return permutations(n, k) / factorial(k);
//}
//
//
///* ____________________________________________________________________________________________________________ */
//// Solving aX + bY = c for X and Y while given a, b, c and all (a, b, c, X, Y) are Integers
//
//void move1step(long long& a, long long& b, const long long& q)
//{
//    long long c = a - q*b;
//    a = b;
//    b = c;
//}
//
//long long eGCD(long long r0, long long r1, long long& x0, long long& y0)
//{
//    //returns the GCD(a, b) and finds X and Y that statesfies that  aX + bY = GCD(a, b)
//    long long x1 = y0 = 0, y1 = x0 = 1;
//    while(r1)
//    {
//        long long q = r0/r1;
//        move1step(r0, r1, q);
//        move1step(x0, x1, q);
//        move1step(y0, y1, q);
//    }
//    return r0;
//}
//
//bool solveLDE(long long a, long long b, long long c, long long& x, long long& y, long long& g)
//{
//    //Returns true if aX + bY = C is slovable given a, b, c and a, b, c, X, Y are integers
//    //Also the values of X and Y that Statesfies the equation aX + bY = C is stored in &x, &y
//    g = eGCD(a, b, x, y);
//    long long m = c/g;
//    x *= m;
//    y *= m;
//    return (c%g == 0);
//}
//
//void getAnotherX_AnotherY(long long &x, long long &y, long long a, long long b, long long k, long long gcd)
//{
//    // Gets another integer x and another integer y that statestfies aX + bY = C
//    x = x + (k * (b / gcd));
//    y = y - (k * (a / gcd));
//}
//
//vector<long long> generateDevisors(long long n)
//{
//    // O(sqrt(n))
//    vector<long long> v;
//    long long i;
//    for(i = 1; i < n / i; ++i)
//    {
//        if(n % i == 0)
//            v.push_back(i), v.push_back(n / i);
//    }
//    if(i * i == n)
//        v.push_back(i);
//    return v;
//}
//
//long long lcm(long long a, long long b)
//{
//    return (a / __gcd(a, b)) * b;
//}
//
///*______________________________________________________________________________________________________________________*/
//
//long long fixMod(long long v, long long modulo)
//{
//    return ((v % modulo) + modulo) % modulo;
//}
//
//
//
//
//
//
//
///* ___________________________ DSU __________________________________*/
//
//
//
//int parent[N], sz[N], comps, mxComp;
//
//void init(){
//    iota(parent, parent+n, 0);
//    fill(sz, sz+n, 1);
//    comps = n;
//    mxComp = 1;
//}
//
//int find(int u){
//    return u == parent[u] ? u : parent[u] = find(parent[u]);
//}
//
//void join(int u, int v){
//    u = find(u);
//    v = find(v);
//    if(u == v)  return;
//    if(sz[u] > sz[v])   swap(u, v);
//    parent[u] = v;
//    sz[v] += sz[u];
//    --comps;
//    mxComp = max(mxComp, sz[v]);
//}


Measured memory_bytes: 256