#include <bits/stdc++.h>
using namespace std;

#define int long long
#define REP(i, n) for (int i = 0; i < (n); i++)
#define FOR(i, m, n) for (int i = (m); i < (n); i++)
constexpr int MOD = 1e9 + 7;
constexpr int MAX = 3000;
int siz[MAX], par[MAX], Rank[MAX];
std::random_device rd;
std::mt19937 mt(rd());
void init(int n) {
    REP(i, n) {
        par[i] = i;
        Rank[i] = 0;
        siz[i] = 1;
    }
}
int find(int x) {
    if (par[x] == x)
        return x;
    else {
        return par[x] = find(par[x]);
    }
}
void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (Rank[x] < Rank[y]) {
        par[x] = y;
        siz[x] += siz[y];
        siz[y] = siz[x];
    } else {
        siz[y] += siz[x];
        siz[x] = siz[y];
        par[y] = x;
        if (Rank[x] == Rank[y]) Rank[x]++;
    }
}
bool same(int x, int y) { return find(x) == find(y); }

using pii = pair<int, int>;
int dx[8] = {1, -1, 0, 0, 1, 1, -1, -1}, dy[8] = {0, 0, -1, 1, -1, 1, -1, 1};
int rnd[10010];

struct image {
    int H, W;
    char A[110][110];
    int id[110][110];
    int height[10010];
    bool done[110][110];
    vector<vector<int>> G;
    bool added[10010];
    int idx;
    int hash;
    image(int H, int W) : H(H), W(W) {}
    void init() {
        REP(i, H + 2) REP(j, W + 2) {
            A[i][j] = '.';
            done[i][j] = false;
        }
        FOR(i, 1, H + 1) {
            FOR(j, 1, W + 1) { cin >> A[i][j]; }
        }
        REP(i, 10010) added[i] = false;
        idx = 0;
    }
    void bfs(int i, int j, int num) {
        done[i][j] = true;
        id[i][j] = num;
        queue<pii> que;
        que.push({i, j});
        while (!que.empty()) {
            pii p = que.front();
            que.pop();
            int x = p.first, y = p.second;
            if (A[i][j] == '.') {
                REP(k, 4) {
                    int nx = x + dx[k], ny = y + dy[k];
                    if (nx >= 0 && nx < H + 2 && ny >= 0 && ny < W + 2 && !done[nx][ny] && A[nx][ny] == A[x][y]) {
                        done[nx][ny] = true;
                        id[nx][ny] = num;
                        que.push({nx, ny});
                    }
                }
            } else {
                REP(k, 8) {
                    int nx = x + dx[k], ny = y + dy[k];
                    if (nx >= 0 && nx < H + 2 && ny >= 0 && ny < W + 2 && !done[nx][ny] && A[nx][ny] == A[x][y]) {
                        done[nx][ny] = true;
                        id[nx][ny] = num;
                        que.push({nx, ny});
                    }
                }
            }
        }
    }
    void assign() {
        idx = 0;
        REP(i, H + 2) {
            REP(j, W + 2) {
                if (!done[i][j]) {
                    bfs(i, j, idx);
                    idx++;
                }
            }
        }
    }
    void construct() {
        init();
        assign();
        G.resize(idx);
        added[0] = true;
        REP(i, H + 2) {
            REP(j, W + 2) {
                if (added[id[i][j]])
                    continue;
                else {
                    if (A[i][j] == '.') {
                        REP(k, 4) {
                            int nx = i + dx[k], ny = j + dy[k];
                            if (nx >= 0 && nx < H + 2 && ny >= 0 && ny < W + 2 && added[id[nx][ny]]) {
                                added[id[i][j]] = true;
                                G[id[nx][ny]].push_back(id[i][j]);
                                break;
                            }
                        }
                    } else {
                        REP(k, 8) {
                            int nx = i + dx[k], ny = j + dy[k];
                            if (nx >= 0 && nx < H + 2 && ny >= 0 && ny < W + 2 && added[id[nx][ny]]) {
                                added[id[i][j]] = true;
                                G[id[nx][ny]].push_back(id[i][j]);
                                break;
                            }
                        }
                    }
                }
            }
        }
        // show();
        getheight(0);
        hash = gethash(0);
        // cerr << hash << endl;
    }

    void show() {
        REP(i, H + 2) {
            REP(j, W + 2) { cerr << id[i][j] << " "; }
            cerr << endl;
        }
    }
    int getheight(int n) {
        int res = 1;
        // cerr << n << endl;
        for (auto nxt : G[n]) {
            res = max(res, 1 + getheight(nxt));
        }
        return height[n] = res;
    }
    // nの部分木のハッシュ
    int gethash(int n) {
        int ret = 1;
        for (auto nxt : G[n]) {
            ret *= (rnd[height[n]] + gethash(nxt));
            ret %= MOD;
        }
        return ret;
    }
};

int H, W;
bool solve() {
    cin >> H >> W;
    if (H == 0) return false;
    image I1(H, W);
    I1.construct();
    cin >> H >> W;
    image I2(H, W);
    I2.construct();
    if (I1.hash == I2.hash)
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    return true;
}
signed main() {
    // init();
    FOR(i, 1, 10000) rnd[i] = mt() % MOD;
    while (solve())
        ;
}


Measured memory_bytes: 3472