cppAcademy
FROM LEARNING TO COMPETING

Intermediate.
Put your skills to the test.

Bulgarian Informatics Group D · 2007–2026

270 independently explained problems: 54 Municipal, 54 Regional, 105 National Olympiad and 57 Autumn Tournament tasks. Start with the easier tasks and work upwards. Difficulty labels are learning estimates, not official ratings; Group D also includes challenging national-level problems. The six 2017 National tasks shared by Groups C and D use their existing permanent URLs. Years follow Arena’s competition-season labels. Source clarifications and special grader requirements are noted on affected tasks.
GROUP D2014 · EasyFrequency counting

Common Rearranged Substring

Autumn Tournament (2014)

Submission name: substring.cpp

Problem summary

You may independently rearrange two lowercase strings. Find the longest string that can occur as a contiguous substring of both rearrangements. Among maximum-length answers, print the lexicographically smallest.

Input

Two lowercase strings on separate lines.

Output

The required string on one line; an empty line if no letter is shared.

Constraints

Each string has at most 1000 characters.

Worked example

Original statement sample.

Input

autumn
tournament

Output

amntu

Solution analysis

  1. Rearranging removes all restrictions on original positions. A candidate substring can be placed at the beginning of a rearrangement precisely when it uses no more copies of any letter than the original string contains.
  2. Count each of the 26 letters in both strings. The common substring can use at most min(countA[c],countB[c]) copies of letter c. Taking this many copies of every letter maximizes its length.
  3. To make that maximum-length answer lexicographically smallest, output its letters in alphabetical order. In autumn and tournament the shared counts give one each of a, m, n, t, u, hence amntu. The extra t in tournament cannot be used because autumn has only one.

Why it works

Every answer is bounded independently by the smaller frequency of each letter. Taking every such available occurrence meets all bounds simultaneously and can be embedded in both rearrangements. No longer answer is possible. Sorting these chosen letters gives their smallest lexicographic permutation.

Complexity: O(A+B+26) time plus output, and O(26) auxiliary space. A and B are the input lengths.

Watch out. This is not the ordinary longest common substring or subsequence problem: arbitrary permutations are allowed. Preserve repeated letters up to their shared counts. No common letters means an empty output line.

Commented C++17 solution

An independently written complete program with standard headers.

// Key idea: Every answer is bounded independently by the smaller frequency of each letter. Taking
// every such available occurrence meets all bounds simultaneously and can be embedded in both
// rearrangements.
#include<algorithm>
#include<array>
#include<iostream>
#include<string>
using namespace std;
int main(){
    string first;
    string second;
    cin>>first>>second;
    array<int,26>countFirst{};
    array<int,26>countSecond{};
    for(char letter:first){
        ++countFirst[letter-'a'];
    }
    for(char letter:second){
        ++countSecond[letter-'a'];
    }
    for(int index=0;index<26;++index){
        int copies=min(countFirst[index],countSecond[index]);
        cout<<string(copies,static_cast<char>('a'+index));
    }
    cout<<'\n';
}

Source: Arena Olimpiici ↗