Official Editorial (C++ and Python)

Explanation

Notation

In C++ and Python, strings can be concatenated using the '+' operator and lexicographically compared using '<' and '>'. We will be using this notation in the solution below.

Solution

The rigorous proof of the method used to solve this problem is available on Codeforces and beyond the scope of USACO Silver. However, we present here how one might arrive at this solution and be convinced that it works.

Warning: Bogus Solution

Simply sort the strings lexicographically and then concatenate.

If all the strings in the input had the same length, we can prove that this solution would in fact work.

Proof of above

However, this method does not work in this problem as strings do not have to be the same length. For example, with the testcase:

4
z
za
b
by

The best concatenation would be "bbyzaz".

However, depending on how you personally define "lexicographically smaller", you may either get "bbyzza" or "bybzaz". Neither of these are the correct answer.

The reason why the solution fails here is because it doesn't make sense to compare two strings of different lengths since you don't know what can appear in the gap left by the shorter string.

b?
by
(If we don't know '?' we can't be sure which is smaller)

Therefore, for this problem, it only ever makes sense to compare strings of same length. To do this, when deciding which of strings aa or bb goes first, we can instead compare a+ba + b and b+ab + a, which have the same length.

bby
byb
(No uncertainty at all, "bby" is smaller)

Though this is not a rigorous proof, this is how one may arrive at the solution and convince themselves that it works. For the rigorous proof by Lewis Gan, check the official editorial linked above.

Time Complexity: O(nlog(N)ai)\mathcal{O}(n \log(N) \cdot |a_i|)

Implementation

C++

#include <bits/stdc++.h>
using namespace std;
bool comp(const string &a, const string &b) { return (a + b) < (b + a); }
int main() {
int n;
cin >> n;
vector<string> inps(n);

Java

import java.util.Arrays;
import java.util.Scanner;
public class Smallest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String[] inps = new String[n];
for (int i = 0; i < n; i++) inps[i] = sc.next();
sc.close();

Python

from functools import cmp_to_key
n = int(input())
inps = []
for _ in range(n):
inps.append(input())
def compare(x: str, y: str) -> int:
if x + y > y + x: # y should come before x

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!