AOJ 1613 Deciphering Characters

解法

包含関係は,一番背景連結成分を根とした木構造になっていることがわかる.
よって,背景連結成分を根として,各再帰段階でBFSをするDFSを行えば,その木構造が得られる.
あとは,木が同一のものであるかを判定する必要があるが,これは木を文字列によって表現することで実現ができる(ノードの数はそんなに多くないはずなので).
各ノードの部分木を表す文字列が得られれば,それをソートして結合し,括弧でくくったものを返せば,木の一意的な表現が得られる.

ソースコード

#include <bits/stdc++.h>
using namespace std;
 
using pii = pair<int, int>;
 
constexpr int dx[2][8] = {{0, 1, 0, -1, 0, 0, 0, 0}, {0, 1, 1, 1, 0, -1, -1, -1}};
constexpr int dy[2][8] = {{1, 0, -1, 0, 0, 0, 0, 0}, {-1, -1, 0, 1, 1, 1, 0, -1}};
 
string dfs(int y, int x, vector<vector<bool>>& visited, vector<string> const& v) {
    const int H = v.size();
    const int W = v[0].size();
    bool black = v[y][x] == '#';
    visited[y][x] = true;
    queue<pii> que;
    que.push(make_pair(y, x));
    vector<pii> next;
    while(!que.empty()) {
        auto p = que.front();
        int y2 = p.first,
            x2 = p.second;
        que.pop();
        for(int i = 0; i < (black ? 8 : 4); ++i) {
            int ny = y2 + dy[black][i],
                nx = x2 + dx[black][i];
            if(ny < 0 || H <= ny || nx < 0 || W <= nx || visited[ny][nx]) {
                continue;
            }
            if(v[ny][nx] != v[y][x]) {
                next.push_back(make_pair(ny, nx));
            } else {
                visited[ny][nx] = true;
                que.push(make_pair(ny, nx));
            }
        }
    }
 
    string res = "(";
    vector<string> tmp;
    for(auto& to : next) {
        if(visited[to.first][to.second]) {
            continue;
        }
        tmp.push_back(dfs(to.first, to.second, visited, v));
    }
    sort(tmp.begin(), tmp.end());
    for(auto& s : tmp) {
        res += move(s);
    }
    res += ")";
    return res;
}
 
int main() {
    int h1, w1;
    while(cin >> h1 >> w1, h1) {
        vector<string> v(h1 + 2, string(w1 + 2, '.'));
        vector<vector<bool>> visited1(h1 + 2, vector<bool>(w1 + 2));
        for(int i = 1; i <= h1; ++i) {
            string s;
            cin >> s;
            v[i] = "." + s + ".";
        }
        int h2, w2;
        cin >> h2 >> w2;
        vector<string> v2(h2 + 2, string(w2 + 2, '.'));
        vector<vector<bool>> visited2(h2 + 2, vector<bool>(w2 + 2));
        for(int i = 1; i <= h2; ++i) {
            string s;
            cin >> s;
            v2[i] = "." + s + ".";
        }
        bool same = dfs(0, 0, visited1, v) == dfs(0, 0, visited2, v2);
        cout << (same ? "yes" : "no") << endl;
    }
}