Deciphering Characters

Image data which are left by a mysterious syndicate were discovered. You are requested to analyze the data. The syndicate members used characters invented independently. A binary image corresponds to one character written in black ink on white paper.

Although you found many variant images that represent the same character, you discovered that you can judge whether or not two images represent the same character with the surrounding relation of connected components. We present some definitions as follows. Here, we assume that white pixels fill outside of the given image.

* White connected component : A set of white pixels connected to each other horizontally or vertically (see below).
* Black connected component : A set of black pixels connected to each other horizontally, vertically, or diagonally (see below).
* Connected component : A white or a black connected component.
* Background component : The connected component including pixels outside of the image. Any white pixels on the periphery of the image are thus included in the background component.



<image> | <image> | <image> | <image>
---|---|---|---
connected | disconnected | connected | connected
Connectedness of white pixels      | Connectedness of black pixels

Let C1 be a connected component in an image and C2 be another connected component in the same image with the opposite color. Let's think of a modified image in which colors of all pixels not included in C1 nor C2 are changed to that of C2. If neither C1 nor C2 is the background component, the color of the background component is changed to that of C2. We say that C1 surrounds C2 in the original image when pixels in C2 are not included in the background component in the modified image. (see below)

<image>

Two images represent the same character if both of the following conditions are satisfied.

* The two images have the same number of connected components.
* Let S and S' be the sets of connected components of the two images. A bijective function f : S -> S' satisfying the following conditions exists.
* For each connected component C that belongs to S, f (C) has the same color as C.
* For each of C1 and C2 belonging to S, f (C1) surrounds f (C2) if and only if C1 surrounds C2.



Let's see an example. Connected components in the images of the figure below has the following surrounding relations.

* C1 surrounds C2.
* C2 surrounds C3.
* C2 surrounds C4.
* C'1 surrounds C'2.
* C'2 surrounds C'3.
* C'2 surrounds C'4.

A bijective function defined as f (Ci) = C'i for each connected component satisfies the conditions stated above. Therefore, we can conclude that the two images represent the same character.

<image> | <image>
---|---

Make a program judging whether given two images represent the same character.

Input

The input consists of at most 200 datasets. The end of the input is represented by a line containing two zeros. Each dataset is formatted as follows.

image 1
image 2

Each image has the following format.

h w
p(1,1) ... p(1,w)
...
p(h,1) ... p(h,w)


h and w are the height and the width of the image in numbers of pixels. You may assume that 1 ≤ h ≤ 100 and 1 ≤ w ≤ 100. Each of the following h lines consists of w characters. p(y,x) is a character representing the color of the pixel in the y-th row from the top and the x-th column from the left. Characters are either a period ("`.`") meaning white or a sharp sign ("`#`") meaning black.

Output

For each dataset, output "`yes`" if the two images represent the same character, or output "`no`", otherwise, in a line. The output should not contain extra characters.

Sample Input


3 6
.#..#.
.##.#
.#..#.
8 7
.#####.
.....#
..#..#
.#.#.#
..#..#
..#..#
.#####.
...#...
3 3
..
...
..
3 3
..
.#.
..
3 3
...
...
...
3 3
...
.#.
...
3 3
.#.
.#
.#.
3 3
.#.

.#.
7 7
.#####.
.....#
..#..#
.#.#.#
..#..#
.....#
.#####.
7 7
.#####.
.....#
..#..#
.#.#.#
..#..#
..#..#
.#####.
7 7
.#####.
.....#
..#..#
.#.#.#
..#..#
.....#
.#####.
7 11
.#####.....
.....#....
..#..#..#.
.#.#.#.#.#
..#..#..#.
.....#....
.#####.....
7 3
.#.
.#
.#.
.#
.#.
.#
.#.
7 7
.#####.
..#..#
..#..#
.#.#.#
..#..#
..#..#
.#####.
3 1


.
1 2
.
0 0


Output for the Sample Input


yes
no
no
no
no
no
yes
yes






Example

Input

3 6
.#..#.
#.##.#
.#..#.
8 7
.#####.
#.....#
#..#..#
#.#.#.#
#..#..#
#..#..#
.#####.
...#...
3 3
#..
...
#..
3 3
#..
.#.
#..
3 3
...
...
...
3 3
...
.#.
...
3 3
.#.
#.#
.#.
3 3
.#.
###
.#.
7 7
.#####.
#.....#
#..#..#
#.#.#.#
#..#..#
#.....#
.#####.
7 7
.#####.
#.....#
#..#..#
#.#.#.#
#..#..#
#..#..#
.#####.
7 7
.#####.
#.....#
#..#..#
#.#.#.#
#..#..#
#.....#
.#####.
7 11
.#####.....
#.....#....
#..#..#..#.
#.#.#.#.#.#
#..#..#..#.
#.....#....
.#####.....
7 3
.#.
#.#
.#.
#.#
.#.
#.#
.#.
7 7
.#####.
#..#..#
#..#..#
#.#.#.#
#..#..#
#..#..#
.#####.
3 1
#
#
.
1 2
#.
0 0


Output

yes
no
no
no
no
no
yes
yes
#include <bits/stdc++.h>

using namespace std;

vector<vector<bool>> Input() {
    int h, w;
    cin >> h >> w;
    if (h == 0 && w == 0) return {};

    vector<vector<bool>> image(h + 2, vector<bool>(w + 2, true));
    for (int i = 0; i < h; ++i)
        for (int j = 0; j < w; ++j) {
            char c;
            cin >> c;
            image[i + 1][j + 1] = (c == '.');
        }

    return image;
}

vector<set<int>> Tree(const vector<vector<bool>> &image) {
    const int h = image.size(), w = image.front().size();
    vector<set<int>> tree;
    vector<vector<int>> idx(h, vector<int>(w, -1));

    const int dx[] = {0, -1, 1, 0, -1, 1, -1, 1};
    const int dy[] = {-1, 0, 0, 1, -1, -1, 1, 1};
    for (int y = 0; y < h; ++y) {
        for (int x = 0; x < w; ++x) {
            if (idx[y][x] != -1) continue;

            int cur_idx = idx[y][x] = tree.size();
            tree.emplace_back();

            stack<pair<int, int>> st;
            st.push(make_pair(y, x));
            while (!st.empty()) {
                const int cur_y = st.top().first, cur_x = st.top().second;
                st.pop();

                for (int dir = 0; dir < (image[cur_y][cur_x] ? 4 : 8); ++dir) {
                    const int ny = cur_y + dy[dir], nx = cur_x + dx[dir];
                    if (ny < 0 || nx < 0 || h <= ny || w <= nx) continue;

                    if (idx[ny][nx] != -1 && idx[ny][nx] != idx[cur_y][cur_x]) {
                        tree[cur_idx].insert(idx[ny][nx]);
                        tree[idx[ny][nx]].insert(cur_idx);
                    }
                    else if (idx[ny][nx] == -1 && (image[cur_y][cur_x] == image[ny][nx])) {
                        st.push(make_pair(ny, nx));
                        idx[ny][nx] = cur_idx;
                    }
                }
            }
        }
    }

    return tree;
}

string Coding(const int par, const int cur, const vector<set<int>> &tree) {
    vector<string> child;

    for (auto v : tree[cur])
        if (v != par) child.emplace_back(Coding(cur, v, tree));

    sort(child.begin(), child.end());
    string code = "(";
    for (const auto &c : child) code += c;

    return code + ")";
}

inline bool Isomorphism(const vector<set<int>> &t1, const vector<set<int>> &t2) {
    return Coding(-1, 0, t1) == Coding(-1, 0, t2);
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    while (true) {
        auto image1(Input());
        if (image1.empty()) break;
        auto image2(Input());

        cout << (Isomorphism(Tree(image1), Tree(image2)) ? "yes" : "no") << '\n';
    }

    return 0;
}

