AOJ 2740 みさわさんの根付き木
問題文
2つの根付き木A,Bが文字列で与えられる.(|A|, |B| <= 1000)
根付き木の各ノードは値と左右の子(or nullptr)を持つ.
二分木を合成してできる二分木を入力と同じ形式にして出力せよ.
解法
構文解析. 書き始める前に以下のページを読んだ.
構文解析 Howto · GitHub
BNF っぽく書くと
tree := "" | '(' tree ')' '[' number ']' '(' tree ')'
number := テキトウ
になるのでパーサーを書く.
自分は二分木データ構造を作ってから A, B を各々二分木にし,愚直に合成してから文字列に戻す, という解き方をした.
ソースコード
http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=3655784
#include "bits/stdc++.h" using namespace std; // パースする文字列 string s; // 次に読み始める位置 int pos; // 二分木ノード struct Node { int val; Node *l, *r; }; // tr := (tr)[num](tr) // 整数 int number() { int ret = 0; while (isdigit(s[pos])) { ret *= 10; ret += s[pos] - '0'; pos++; } return ret; } // パースして二分木のノードを返す Node *misawa() { if (s[pos] == ')') { // 空ノード return nullptr; } pos++; // ( auto l = misawa(); // left child pos++; // ) pos++; // [ auto v = number(); pos++; // ] pos++; // ( auto r = misawa(); // right child pos++; // ) Node *node = new Node; node->val = v; node->l = l; node->r = r; return node; } // 二分木a, b を合成 Node *rec(Node *a, Node *b) { Node *ret = new Node; ret->val = a->val + b->val; ret->l = nullptr; ret->r = nullptr; if (a->l && b->l) { ret->l = rec(a->l, b->l); } if (a->r && b->r) { ret->r = rec(a->r, b->r); } return ret; } // 二分木を文字列に変換 string recstr(Node *node) { if (node == nullptr) return ""; string ret = ""; ret += "(" + recstr(node->l) + ")"; ret += "[" + to_string(node->val) + "]"; ret += "(" + recstr(node->r) + ")"; return ret; } int main() { cin.tie(0); ios::sync_with_stdio(false); string a, b; cin >> a >> b; s = a; pos = 0; auto at = misawa(); s = b; pos = 0; auto bt = misawa(); auto ret = rec(at, bt); cout << recstr(ret) << endl; }
感想
パーサーより二分木がバグりそう