You're given a list of n strings a_1, a_2, ..., a_{n}. You'd like to concatenate them together in some order such that the resulting string would be lexicographically smallest.

Given the list of strings, output the lexicographically smallest concatenation.


-----Input-----

The first line contains integer n — the number of strings (1 ≤ n ≤ 5·10^4).

Each of the next n lines contains one string a_{i} (1 ≤ |a_{i}| ≤ 50) consisting of only lowercase English letters. The sum of string lengths will not exceed 5·10^4.


-----Output-----

Print the only string a — the lexicographically smallest string concatenation.


-----Examples-----
Input
4
abba
abacaba
bcd
er

Output
abacabaabbabcder

Input
5
x
xx
xxa
xxaa
xxaaa

Output
xxaaaxxaaxxaxxx

Input
3
c
cb
cba

Output
cbacbc

Source: codeforces | Difficulty: MEDIUM_HARD
Tags: String algorithms

Sorting


Solutions:
from functools import cmp_to_key as ctk
s = []
for o in range(int(input())):
	s += [input()]
s.sort(key=ctk(lambda x, y: 1 if x + y > y + x else -1))
print(''.join(s))


n = int(input())
strArr = []
for x in range(n):
	strArr.append(input())

def sortStrByOrder(strArr):
	if strArr == None or len(strArr) == 0:
		return ''
	from functools import cmp_to_key
	strArr = sorted(strArr, key=cmp_to_key(lambda x, y: 1 if x + y > y + x else -1))
	str = ''
	for x in strArr:
		str += x
	return str
print(sortStrByOrder(strArr))


class own(object):

	def __init__(self, a):
		self.a = a

	def __lt__(self, other):
		return self.a + other.a < other.a + self.a

def main():
	n = int(input())
	l = [own(input()) for i in range(n)]
	l = sorted(l)
	for i in l:
		print(i.a, end='')
main()


from functools import cmp_to_key
n = int(input())
a = []
for i in range(n):
	a.append(input())

def cmp(x, y):
	if x + y < y + x:
		return -1
	elif x + y > y + x:
		return 1
	else:
		return 0
print(''.join(sorted(a, key=cmp_to_key(cmp))))


import functools
import math
import sys

def cmp(x, y):
	if x < y:
		return -1
	elif x > y:
		return 1
	else:
		return 0
print(''.join(sorted([s.rstrip() for s in sys.stdin.readlines()[1:]], key=functools.cmp_to_key(lambda x, y: cmp(x + y, y + x)))))


from functools import cmp_to_key as f
l = []
for o in range(int(input())):
	l += [input()]
print(''.join(sorted(l, key=f(lambda x, y: 1 if x + y > y + x else -1))))


from functools import cmp_to_key as cmptokey
n = int(input())
s = []
for i in range(n):
	s += [input()]
s.sort(key=cmptokey(lambda x, y: 1 if x + y > y + x else -1))
print(''.join(s))


from functools import cmp_to_key
a = [input() for _ in range(int(input()))]
print(''.join(sorted(a, key=cmp_to_key(lambda x, y: 1 if x + y > y + x else -1))))


from functools import cmp_to_key
n = int(input())
S = []
for i in range(n):
	S.append(input())
S.sort(key=cmp_to_key(lambda x, y: 1 if x + y > y + x else -1))
print(''.join(S))


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def list2d(a, b, c):
	return [[c] * b for i in range(a)]

def list3d(a, b, c, d):
	return [[[d] * c for j in range(b)] for i in range(a)]

def list4d(a, b, c, d, e):
	return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]

def ceil(x, y=1):
	return int(-(-x // y))

def Yes():
	print('Yes')

def No():
	print('No')

def YES():
	print('YES')

def NO():
	print('NO')
INF = 10 ** 18
MOD = 10 ** 9 + 7
from functools import cmp_to_key
Ri = lambda : [int(x) for x in sys.stdin.readline().split()]
ri = lambda : sys.stdin.readline().strip()
n = int(ri())
s = []
for i in range(n):
	s.append(ri())
s.sort(key=cmp_to_key(lambda x, y: -1 if x + y < y + x else 1))
print(''.join(s))


import functools

def compare(s1: str, s2: str):
	s = s1 + s2
	r = s2 + s1
	if s > r:
		return 1
	elif s == r:
		return 0
	else:
		return -1

def main():
	n = int(input())
	ans = []
	for _ in range(n):
		ans.append(input())
	ans = sorted(ans, key=functools.cmp_to_key(compare))
	print(''.join(ans))
main()


from functools import cmp_to_key as k

def c(x, y):
	return -1 if x + y < y + x else 1
n = int(input())
l = [input() for _ in range(n)]
print(''.join(sorted(l, key=k(c))))


from functools import cmp_to_key
from collections import deque, Counter
from heapq import heappush, heappop
from math import log, ceil
import sys
import os
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()

def inp():
	return sys.stdin.readline().rstrip('\r\n')

def ii():
	return int(inp())

def si():
	return str(inp())

def li(lag=0):
	l = list(map(int, inp().split()))
	if lag != 0:
		for i in range(len(l)):
			l[i] += lag
	return l

def mi(lag=0):
	matrix = list()
	for i in range(n):
		matrix.append(li(lag))
	return matrix

def lsi():
	return list(map(str, inp().split()))

def print_list(lista, space=' '):
	print(space.join(map(str, lista)))

def bisect_left(a, x):
	left = 0
	right = len(a)
	while left < right:
		mid = (left + right) // 2
		if a[mid] < x:
			left = mid + 1
		else:
			right = mid
	return left

def bisect_right(a, x):
	left = 0
	right = len(a)
	while left < right:
		mid = (left + right) // 2
		if a[mid] > x:
			right = mid
		else:
			left = mid + 1
	return left

def bisect_elements(a, x):
	return bisect_right(a, x) - bisect_left(a, x)
MOD = 10 ** 9 + 7
maxN = 5
FACT = [0] * maxN
INV_FACT = [0] * maxN

def add(x, y):
	return (x + y) % MOD

def multiply(x, y):
	return x * y % MOD

def power(x, y):
	if y == 0:
		return 1
	elif y % 2:
		return multiply(x, power(x, y - 1))
	else:
		a = power(x, y // 2)
		return multiply(a, a)

def inverse(x):
	return power(x, MOD - 2)

def divide(x, y):
	return multiply(x, inverse(y))

def allFactorials():
	FACT[0] = 1
	for i in range(1, maxN):
		FACT[i] = multiply(i, FACT[i - 1])

def inverseFactorials():
	n = len(INV_FACT)
	INV_FACT[n - 1] = inverse(FACT[n - 1])
	for i in range(n - 2, -1, -1):
		INV_FACT[i] = multiply(INV_FACT[i + 1], i + 1)

def coeffBinom(n, k):
	if n < k:
		return 0
	return multiply(FACT[n], multiply(INV_FACT[k], INV_FACT[n - k]))

def create_graph(n, m, undirected=1, unweighted=1):
	graph = [[] for i in range(n)]
	if unweighted:
		for i in range(m):
			[x, y] = li(lag=-1)
			graph[x].append(y)
			if undirected:
				graph[y].append(x)
	else:
		for i in range(m):
			[x, y, w] = li(lag=-1)
			w += 1
			graph[x].append([y, w])
			if undirected:
				graph[y].append([x, w])
	return graph

def create_tree(n, unweighted=1):
	children = [[] for i in range(n)]
	if unweighted:
		for i in range(n - 1):
			[x, y] = li(lag=-1)
			children[x].append(y)
			children[y].append(x)
	else:
		for i in range(n - 1):
			[x, y, w] = li(lag=-1)
			w += 1
			children[x].append([y, w])
			children[y].append([x, w])
	return children

def dist(tree, n, A, B=-1):
	s = [[A, 0]]
	(massimo, massimo_nodo) = (0, 0)
	distanza = -1
	v = [-1] * n
	while s:
		(el, dis) = s.pop()
		if dis > massimo:
			massimo = dis
			massimo_nodo = el
		if el == B:
			distanza = dis
		for child in tree[el]:
			if v[child] == -1:
				v[child] = 1
				s.append([child, dis + 1])
	return (massimo, massimo_nodo, distanza)

def diameter(tree):
	(_, foglia, _) = dist(tree, n, 0)
	(diam, _, _) = dist(tree, n, foglia)
	return diam

def dfs(graph, n, A):
	v = [-1] * n
	s = [[A, 0]]
	v[A] = 0
	while s:
		(el, dis) = s.pop()
		for child in graph[el]:
			if v[child] == -1:
				v[child] = dis + 1
				s.append([child, dis + 1])
	return v

def bfs(graph, n, A):
	v = [-1] * n
	s = deque()
	s.append([A, 0])
	v[A] = 0
	while s:
		(el, dis) = s.popleft()
		for child in graph[el]:
			if v[child] == -1:
				v[child] = dis + 1
				s.append([child, dis + 1])
	return v

def parents_children_root_unrooted_tree(tree, n, root=0):
	q = deque()
	visited = [0] * n
	parent = [-1] * n
	children = [[] for i in range(n)]
	q.append(root)
	while q:
		all_done = 1
		visited[q[0]] = 1
		for child in tree[q[0]]:
			if not visited[child]:
				all_done = 0
				q.appendleft(child)
		if all_done:
			for child in tree[q[0]]:
				if parent[child] == -1:
					parent[q[0]] = child
					children[child].append(q[0])
			q.popleft()
	return (parent, children)

def all_longest_path_passing_from_node(parent, children, n):
	q = deque()
	visited = [len(children[i]) for i in range(n)]
	downwards = [[0, 0] for i in range(n)]
	upward = [1] * n
	longest_path = [1] * n
	for i in range(n):
		if not visited[i]:
			q.append(i)
			downwards[i] = [1, 0]
	while q:
		node = q.popleft()
		if parent[node] != -1:
			visited[parent[node]] -= 1
			if not visited[parent[node]]:
				q.append(parent[node])
		else:
			root = node
		for child in children[node]:
			downwards[node] = sorted([downwards[node][0], downwards[node][1], downwards[child][0] + 1], reverse=True)[0:2]
	s = [node]
	while s:
		node = s.pop()
		if parent[node] != -1:
			if downwards[parent[node]][0] == downwards[node][0] + 1:
				upward[node] = 1 + max(upward[parent[node]], downwards[parent[node]][1])
			else:
				upward[node] = 1 + max(upward[parent[node]], downwards[parent[node]][0])
		longest_path[node] = downwards[node][0] + downwards[node][1] + upward[node] - min([downwards[node][0], downwards[node][1], upward[node]]) - 1
		for child in children[node]:
			s.append(child)
	return longest_path
n = ii()
lista = []
for i in range(n):
	lista.append(si())

def custom_sort(lista):

	def cmp(x, y):
		if x + y > y + x:
			return 1
		else:
			return -1
	return sorted(lista, key=cmp_to_key(cmp))
lista = custom_sort(lista)
print_list(lista, '')


from functools import cmp_to_key

def cmp(a, b):
	x = a + b
	y = b + a
	if x < y:
		return -1
	elif x == y:
		return 0
	return 1
(n, a) = (int(input()), [])
for i in range(n):
	a.append(input())
a.sort(key=cmp_to_key(cmp))
for i in a:
	print(i, end='')


class MyStr:

	def __init__(self, s):
		self.s = s

	def __lt__(self, other):
		if self.s.startswith(other.s):
			return self.s[len(other.s):] + other.s < self.s
		elif other.s.startswith(self.s):
			return other.s < other.s[len(self.s):] + self.s
		else:
			return self.s < other.s
n = int(input())
mss = []
for i in range(n):
	s = input()
	mss.append(MyStr(s))
result = ''
for ms in sorted(mss):
	result += ms.s
print(result)


class cmp(object):

	def __init__(self, t):
		self.t = t

	def __lt__(self, q):
		return self.t + q.t < q.t + self.t
print(''.join((q for q in sorted([input() for i in range(int(input()))], key=cmp))))


from functools import *
print(''.join(sorted([input() for _ in range(int(input()))], key=cmp_to_key(lambda x, y: 2 * (x + y > y + x) - 1))))


from functools import cmp_to_key

def c(x, y):
	if x + y > y + x:
		return 1
	else:
		return -1
n = int(input())
l = []
for _ in range(n):
	l.append(input())
l.sort(key=cmp_to_key(c))
print(''.join(l))


from functools import cmp_to_key

def f(x, y):
	return -1 if x + y < y + x else 1
n = int(input())
A = []
for i in range(n):
	s = input()
	A.append(s)
print(''.join(sorted(A, key=cmp_to_key(f))))


from sys import stdin
from functools import cmp_to_key

def input():
	return stdin.readline()

def mysort(x, y):
	return 1 if x + y > y + x else -1
n = int(input())
strings = []
for i in range(n):
	t = input().strip('\n')
	strings.append(t)
strings.sort(key=cmp_to_key(mysort))
print(''.join(strings))


def mergesort(s):
	if len(s) == 1:
		return s
	s1 = mergesort(s[:len(s) // 2])
	s2 = mergesort(s[len(s) // 2:])
	return merge(s1, s2)

def merge(s1, s2):
	f = []
	ind1 = 0
	ind2 = 0
	while ind1 != len(s1) and ind2 != len(s2):
		if str(s1[ind1]) + str(s2[ind2]) > str(s2[ind2]) + str(s1[ind1]):
			f.append(s2[ind2])
			ind2 += 1
		else:
			f.append(s1[ind1])
			ind1 += 1
	if ind1 != len(s1):
		f.extend(s1[ind1:])
	else:
		f.extend(s2[ind2:])
	return f
n = int(input())
s = []
for i in range(n):
	s.append(input())
print(''.join(mergesort(s)))


from functools import cmp_to_key

def compare(x, y):
	if y + x < x + y:
		return -1
	if x + y < y + x:
		return 1
	if x + y == y + x:
		return 0
n = int(input())
s = []
for i in range(n):
	a = input()
	s.append(a)
r = sorted(s, key=cmp_to_key(compare), reverse=True)
for i in range(n):
	print(r[i], end='')


def main():
	n = int(input())
	strings = [None] * n
	for i in range(n):
		strings[i] = input()
	print(solver(strings))

def solver(L):
	L.sort(key=cmp_to_key(customCompare))
	return ''.join(L)

def customCompare(x, y):
	a = x + y
	b = y + x
	if a < b:
		return -1
	elif a == b:
		return 0
	else:
		return 1

def compareStrings(x, y):
	if x < y:
		return -1
	elif x == y:
		return 0
	else:
		return 1

def isPrefix(s, t):
	if s == t[:len(s)]:
		return True

def cmp_to_key(mycmp):

	class K:

		def __init__(self, obj, *args):
			self.obj = obj

		def __lt__(self, other):
			return mycmp(self.obj, other.obj) < 0

		def __gt__(self, other):
			return mycmp(self.obj, other.obj) > 0

		def __eq__(self, other):
			return mycmp(self.obj, other.obj) == 0

		def __le__(self, other):
			return mycmp(self.obj, other.obj) <= 0

		def __ge__(self, other):
			return mycmp(self.obj, other.obj) >= 0

		def __ne__(self, other):
			return mycmp(self.obj, other.obj) != 0
	return K
main()


from functools import cmp_to_key

def CMP(x, y):
	if x + y > y + x:
		return 1
	else:
		return -1
n = int(input())
L = []
for i in range(n):
	str = input()
	L.append(str)
L.sort(key=cmp_to_key(CMP))
for i in L:
	print(i, end='')


from bisect import insort, bisect_right, bisect_left
from sys import stdout, stdin, setrecursionlimit
from heapq import heappush, heappop, heapify
from io import BytesIO, IOBase
from collections import *
from itertools import *
from random import *
from string import *
from queue import *
from math import *
from re import *
from os import *

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = read(self._fd, max(fstat(self._fd).st_size, 8192))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = read(self._fd, max(fstat(self._fd).st_size, 8192))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(stdin, stdout) = (IOWrapper(stdin), IOWrapper(stdout))
(graph, mod, szzz) = ({}, 10 ** 9 + 7, lambda : sorted(zzz()))

def getStr():
	return input()

def getInt():
	return int(input())

def listStr():
	return list(input())

def getStrs():
	return input().split()

def isInt(s):
	return '0' <= s[0] <= '9'

def input():
	return stdin.readline().strip()

def zzz():
	return [int(i) for i in input().split()]

def output(answer, end='\n'):
	stdout.write(str(answer) + end)

def lcd(xnum1, xnum2):
	return xnum1 * xnum2 // gcd(xnum1, xnum2)

def getPrimes(N=10 ** 5):
	SN = int(sqrt(N))
	sieve = [i for i in range(N + 1)]
	sieve[1] = 0
	for i in sieve:
		if i > SN:
			break
		if i == 0:
			continue
		for j in range(2 * i, N + 1, i):
			sieve[j] = 0
	prime = [i for i in range(N + 1) if sieve[i] != 0]
	return prime

def primeFactor(n, prime=getPrimes()):
	lst = []
	mx = int(sqrt(n)) + 1
	for i in prime:
		if i > mx:
			break
		while n % i == 0:
			lst.append(i)
			n //= i
	if n > 1:
		lst.append(n)
	return lst
dx = [-1, 1, 0, 0, 1, -1, 1, -1]
dy = [0, 0, 1, -1, 1, -1, -1, 1]
daysInMounth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
num = getInt()
lst = []
for _ in range(num):
	lst.append(getStr())

def mergeSort(s):
	if len(s) == 1:
		return s
	s1 = mergeSort(s[:len(s) // 2])
	s2 = mergeSort(s[len(s) // 2:])
	return merge(s1, s2)

def merge(s1, s2):
	lst = []
	ind1 = 0
	ind2 = 0
	while ind1 != len(s1) and ind2 != len(s2):
		if s1[ind1] + s2[ind2] > s2[ind2] + s1[ind1]:
			lst.append(s2[ind2])
			ind2 += 1
		else:
			lst.append(s1[ind1])
			ind1 += 1
	if ind1 != len(s1):
		lst += s1[ind1:]
	else:
		lst += s2[ind2:]
	return lst
print(''.join((i for i in mergeSort(lst))))


def cmp_to_key(mycmp):

	class K:

		def __init__(self, obj, *args):
			self.obj = obj

		def __lt__(self, other):
			return mycmp(self.obj, other.obj) < 0

		def __gt__(self, other):
			return mycmp(self.obj, other.obj) > 0

		def __eq__(self, other):
			return mycmp(self.obj, other.obj) == 0

		def __le__(self, other):
			return mycmp(self.obj, other.obj) <= 0

		def __ge__(self, other):
			return mycmp(self.obj, other.obj) >= 0

		def __ne__(self, other):
			return mycmp(self.obj, other.obj) != 0
	return K
n = int(input())
ls = [input() for _ in range(n)]

def compare_str(x, y):
	if x + y < y + x:
		return -1
	elif x + y > y + x:
		return 1
	else:
		return 0
ls.sort(key=cmp_to_key(compare_str))
print(''.join(ls))


from functools import cmp_to_key
import locale

def cmp(s, t):
	if s + t < t + s:
		return -1
	if s + t > t + s:
		return 1
	return 0
n = int(input())
S = [input() for i in range(n)]
S.sort(key=cmp_to_key(cmp))
print(''.join(S))


from functools import cmp_to_key

def cmp(a, b):
	return -1 if a + b < b + a else 0

def main():
	n = int(input())
	l = [input() for i in range(n)]
	l = sorted(l, key=cmp_to_key(cmp))
	for i in l:
		print(i, end='')
main()


import functools
n = int(input())
a = []
for i in range(n):
	a.append(input())

def cmp_string(s1, s2):
	if s1 + s2 < s2 + s1:
		return -1
	else:
		return 1
a.sort(key=functools.cmp_to_key(cmp_string))
print(''.join(a))


from functools import cmp_to_key

def custom(x, y):
	a = x + y
	b = y + x
	if a < b:
		return -1
	elif b < a:
		return 1
	else:
		return 0
n = int(input())
arr = []
for i in range(n):
	s = input()
	arr.append(s)
arr.sort(key=cmp_to_key(custom))
ans = ''
for i in arr:
	ans += i
print(ans)


from functools import cmp_to_key as ctk
n = int(input())
c = []
for i in range(n):
	c.append(input())

def sort(a, b):
	if a + b < b + a:
		return -1
	else:
		return 1
c.sort(key=ctk(sort))
print(''.join(c))


from functools import cmp_to_key

def comparator(a, b):
	return -1 if a + b <= b + a else 1

def smallest_string(str_list):
	return ''.join(sorted(str_list, key=cmp_to_key(comparator)))
n = int(input())
str_list = []
for _ in range(n):
	s = input()
	str_list.append(s)
print(smallest_string(str_list))


from functools import cmp_to_key

def cmp(x, y):
	if x + y > y + x:
		return 1
	else:
		return -1
a = []
n = int(input())
for i in range(n):
	a.append(input())
ans = ''
for s in sorted(a, key=cmp_to_key(cmp)):
	ans += s
print(ans)


import functools
import sys

def In():
	return map(int, sys.stdin.readline().split())
input = sys.stdin.readline

def mergesort(l):

	def recur(arr):
		if len(arr) > 1:
			mid = len(arr) // 2
			l = arr[:mid]
			r = arr[mid:]
			recur(l)
			recur(r)
			(left, right, pos) = (0, 0, 0)
			while left < len(l) and right < len(r):
				if com(l[left], r[right]):
					arr[pos] = l[left]
					left += 1
				else:
					arr[pos] = r[right]
					right += 1
				pos += 1
			while left < len(l):
				arr[pos] = l[left]
				pos += 1
				left += 1
			while right < len(r):
				arr[pos] = r[right]
				pos += 1
				right += 1
	recur(l)
	print(''.join(l))

def com(x, y):
	return -(x + y < y + x)

def smaconcentra():
	n = int(input())
	l = [input().rstrip() for _ in range(n)]
	l.sort(key=functools.cmp_to_key(com))
	print(''.join(l))
smaconcentra()


n = int(input())

def comp(a, b):
	l = a + b
	r = b + a
	if l < r:
		return -1
	elif l == r:
		return 0
	else:
		return 1
from functools import cmp_to_key
d = []
for _ in range(n):
	s = input().rstrip()
	d.append(s)
d.sort(key=cmp_to_key(comp))
print(''.join(d))


from functools import cmp_to_key
t = int(input())
l = []
for i in range(t):
	x = input()
	l.append(x)
l.sort(key=cmp_to_key(lambda x, y: 1 if x + y > y + x else -1))
for i in range(t):
	print(l[i], end='')


n = int(input())
A = []
for i in range(n):
	A.append(input())

def custom_sort(s1, s2):
	n1 = len(s1)
	n2 = len(s2)
	if n1 == n2:
		if s1 <= s2:
			return -1
		else:
			return 1
	elif s1 + s2 <= s2 + s1:
		return -1
	else:
		return 1
import functools
A.sort(key=functools.cmp_to_key(custom_sort))
print(''.join(A))


from functools import cmp_to_key
n = int(input())
a = []
for i in range(n):
	a.append(input().strip())
a = sorted(a, key=cmp_to_key(lambda x, y: -1 if x + y < y + x else 1))
print(''.join(a))


from functools import cmp_to_key

def cmp(A, B):
	if A + B < B + A:
		return -1
	else:
		return 0

def main():
	N = int(input())
	X = []
	for i in range(N):
		Y = input()
		X.append(Y)
	print(''.join(sorted(X, key=cmp_to_key(cmp))))
main()


def compare(f, u):
	if f + u < u + f:
		return -1
	elif f + u == u + f:
		return 0
	else:
		return 1
from functools import cmp_to_key
n = int(input())
s = []
for i in range(n):
	s.append(input())
print(''.join(sorted(s, key=cmp_to_key(compare))))


from functools import cmp_to_key
n = int(input())
ls = [input() for _ in range(n)]

def compare_str(x, y):
	if x + y < y + x:
		return -1
	elif x + y > y + x:
		return 1
	else:
		return 0
ls.sort(key=cmp_to_key(compare_str))
print(''.join(ls))


from functools import cmp_to_key as ctk

def comp(a, b):
	if a + b < b + a:
		return -1
	elif a + b > b + a:
		return 1
	else:
		return 0
n = int(input())
string = list()
for i in range(n):
	strtem = input()
	string.append(strtem)
string.sort(key=ctk(comp))
print(''.join(string))


from functools import cmp_to_key

def cmpEqLen(a, b):
	if a < b:
		return -1
	elif a > b:
		return 1
	else:
		return 0

def compare(a, b):
	alen = len(a)
	blen = len(b)
	if alen == blen:
		return cmpEqLen(a, b)
	l = min(alen, blen)
	c = cmpEqLen(a[:l], b[:l])
	if c != 0:
		return c
	if alen > blen:
		return -compare(a[:l], a[l:])
	else:
		return compare(b[:l], b[l:])
N = int(input())
arr = [input() for _ in range(N)]
arr.sort(key=cmp_to_key(compare))
print(''.join(arr))


import functools
lst = []
for _ in range(int(input())):
	lst.append(input())

def cmp(a, b):
	if a + b > b + a:
		return 1
	elif a + b < b + a:
		return -1
	else:
		return -0
x = sorted(lst, key=functools.cmp_to_key(cmp))
print(''.join(x))


from functools import cmp_to_key
n = int(input())
stg = []
for i in range(n):
	stg.append(input())
stg = sorted(stg, key=cmp_to_key(lambda a, b: 1 if a + b > b + a else -1))
print(''.join(stg))


def comp(a, b):
	if a + b < b + a:
		return -1
	else:
		return 1
from functools import cmp_to_key
l = []
for _ in range(int(input())):
	l.append(input())
print(''.join(sorted(l, key=cmp_to_key(comp))))


import functools
in1 = int(input())

def newCompare(x, y):
	if x + y > y + x:
		return 1
	else:
		return -1
inputs = []
for x in range(in1):
	inputs.append(input())
inputs = sorted(inputs, key=functools.cmp_to_key(newCompare))
string = ''
for x in inputs:
	string += x
print(string)


from functools import cmp_to_key
n = int(input())
strings = [input() for i in range(n)]

def cmp(s1, s2):
	(z1, z2) = (s1 + s2, s2 + s1)
	if z1 < z2:
		return -1
	elif z2 > z1:
		return 1
	else:
		return 0
strings.sort(key=cmp_to_key(cmp))
for string in strings:
	print(string, end='')
print('')


from functools import cmp_to_key
n = int(input())
a = []
for i in range(n):
	a.append(input())

def str_comp(x1, x2):
	if x1 + x2 < x2 + x1:
		return -1
	else:
		return 1
a_new = sorted(a, key=cmp_to_key(str_comp))
print(''.join(a_new))


from functools import cmp_to_key
n = int(input())
l = [input() for _ in range(n)]

def comparator(a, b):
	return -1 if a + b <= b + a else 1
l = sorted(l, key=cmp_to_key(comparator))
print(''.join(l))


import sys

class Word(object):

	def __init__(self, word):
		self.word = word

	def __lt__(self, other):
		return self.word + other.word < other.word + self.word

	def __str__(self):
		return self.word
n = int(sys.stdin.buffer.readline().decode('utf-8'))
a = list((Word(line.decode('utf-8').rstrip()) for line in sys.stdin.buffer))
a.sort()
sys.stdout.buffer.write(''.join(map(str, a)).encode('utf-8'))


__author__ = 'Utena'
from functools import cmp_to_key
n = int(input())
s = []
for i in range(n):
	s.append(input())

def cmp(x, y):
	if x + y < y + x:
		return -1
	else:
		return 1
s = sorted(s, key=cmp_to_key(cmp))
print(''.join(s))


def cmp_to_key(mycmp):

	class K(object):

		def __init__(self, obj, *args):
			self.obj = obj

		def __lt__(self, other):
			return mycmp(self.obj, other.obj) < 0

		def __gt__(self, other):
			return mycmp(self.obj, other.obj) > 0

		def __eq__(self, other):
			return mycmp(self.obj, other.obj) == 0

		def __le__(self, other):
			return mycmp(self.obj, other.obj) <= 0

		def __ge__(self, other):
			return mycmp(self.obj, other.obj) >= 0

		def __ne__(self, other):
			return mycmp(self.obj, other.obj) != 0
	return K

def cp(a, b):
	if a + b < b + a:
		return 1
	elif b + a < a + b:
		return -1
	return 0
n = int(input())
k = []
for i in range(n):
	s = input().strip()
	k.append(s)
k.sort(key=cmp_to_key(cp), reverse=True)
print(''.join(k))


from functools import cmp_to_key
n = int(input())
strings = list()
for i in range(n):
	strings.append(input())

def cmpfunc(x, y):
	a = x + y
	b = y + x
	if a < b:
		return -1
	elif a == b:
		return 0
	else:
		return 1
bb = sorted(strings, key=cmp_to_key(cmpfunc))
print(''.join(bb))