Two Charts Become One

At the time of writing, this problem has a difficulty rating of 6.7 on Kattis, which qualifies as a Hard. It's fresh from the contest — I think the difficulty will even out to around a 4.5.

A fun parsing problem. Given two strings that describe hierarchical organizations (rooted trees), determine if the hierarchies are the same.

The general steps are as follows:

  1. Construct the hierarchy (tree) described by each string (stack-based parsing exercise)
  2. Ensure the head departments (roots) of the hierarchies are the same.
  3. DFS on one of the hierarchies, ensuring the current department is present in the other hierarchy.

_101
#include <iostream>
_101
#include <string>
_101
#include <unordered_map>
_101
#include <set>
_101
#include <stack>
_101
_101
using hierarchy = std::unordered_map<int, std::set<int>>;
_101
_101
template <class II>
_101
int next_int(II& it, II& end);
_101
_101
/**
_101
* Parse a chart string of the following form:
_101
*
_101
* <hierarchy> ::= <department number> (<hierarchy>)*
_101
*
_101
* In this case, the leading (head) department in a hierarchy
_101
* is in charge of all the subsequent parenthesised hierarchies.
_101
*
_101
* For example, the chart string '11 (10) (12 (13) (17) (28))'
_101
* corresponds to the following hierarchy:
_101
*
_101
* 11 (the head department)
_101
* / \
_101
* 10 12
_101
* / | \
_101
* 13 17 28
_101
*/
_101
auto parse_chart (const std::string& chart_string) -> std::pair<int, hierarchy> {
_101
auto it = chart_string.begin();
_101
auto end = chart_string.end();
_101
hierarchy org;
_101
std::stack<int> roots;
_101
int head = next_int(it, end);
_101
roots.push(head);
_101
_101
while (it != end) {
_101
switch (*it) {
_101
case ' ': { it++; break; }
_101
case '(': { it++; break; }
_101
case ')': { it++; roots.pop(); break; }
_101
_101
// the 0-9 case
_101
default: {
_101
int x = next_int(it, end);
_101
org[roots.top()].insert(x);
_101
roots.push(x);
_101
}
_101
}
_101
}
_101
_101
return {head, org};
_101
}
_101
_101
int main () {
_101
std::string a,b;
_101
std::getline(std::cin, a);
_101
std::getline(std::cin, b);
_101
_101
auto [r1, org1] = parse_chart(a);
_101
auto [r2, org2] = parse_chart(b);
_101
_101
if (r1 != r2) {
_101
std::cout << "No\n";
_101
return 0;
_101
}
_101
_101
std::stack<int> stk;
_101
stk.push(r1);
_101
_101
// walk through the first hierarchy,
_101
// confirming it's the same as all the other hierarchies.
_101
while (!stk.empty()) {
_101
int r = stk.top();
_101
stk.pop();
_101
_101
if (org1[r] != org2[r]) {
_101
std::cout << "No\n";
_101
return 0;
_101
}
_101
_101
for (auto child : org1[r]) {
_101
stk.push(child);
_101
}
_101
}
_101
std::cout << "Yes\n";
_101
}
_101
_101
/**
_101
* Read an integer from a string iterator,
_101
* advancing the iterator. We trust there's a int here.
_101
* */
_101
template <class II>
_101
int next_int(II& it, II& end) {
_101
int x = 0;
_101
while (it != end && *it >= '0' && *it <= '9') {
_101
x *= 10;
_101
x += *it++ - '0';
_101
}
_101
return x;
_101
}

If you found this solution helpful, consider leaving a star!