#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


enum Type{
	WHITE,
	BLACK,
};

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};


struct Node{
	int parent;
	vector<int> children;
};

int H,W;
int diff_row_white[4] = {-1,0,0,1},diff_col_white[4] = {0,-1,1,0};
int diff_row_black[8] = {-1,-1,-1,0,0,1,1,1},diff_col_black[8] = {-1,0,1,-1,1,-1,0,1};
int boss[15000],height[15000];
int boss_index[15000];
int num_descendants[2][2501];
char input[100][101];
char table[2][102][102]; //外側にダミーセルを敷いたマップ
bool used[102][102],is_adj[2501][2501];
vector<int> ADJ[10000],RESULT[2];
Node nodes[2][2501];


//自分のボスのindexを取得しつつ、経路圧縮を行う関数
int get_boss(int id){
	if(boss[id] == id)return id; //自分が代表なら、自分の値を返す
	else{
		return boss[id] = get_boss(boss[id]); //代表でないなら、自分が所属する組織の代表を返しつつ、経路圧縮
	}
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

//2次元を1次元にする
int get_index(int row,int col){
	return W*row+col;
}


bool rangeCheck(int row,int col){
	if(row >= 0 && row <= H-1 && col >= 0 && col <= W-1)return true;
	else{
		return false;
	}
}

void makeTree(int loop,int node_id,int pre_node){

	if(pre_node != -1){
		nodes[loop][node_id].parent = pre_node;
		nodes[loop][pre_node].children.push_back(node_id);
	}
	for(int i = 0; i < ADJ[node_id].size(); i++){
		if(ADJ[node_id][i] == pre_node)continue;
		makeTree(loop,ADJ[node_id][i],node_id);
	}
}

vector<int> makeArray(int loop,int node_id){
	vector<int> ret;
	if(nodes[loop][node_id].children.size() == 0){
		ret.push_back(0);
		return ret;
	}

	vector<vector<int>> mid;
	for(int i = 0; i < nodes[loop][node_id].children.size(); i++){
		mid.push_back(makeArray(loop,nodes[loop][node_id].children[i]));
	}
	sort(mid.begin(),mid.end());

	for(int i = 0; i < mid.size(); i++){
		for(int k = 0; k < mid[i].size(); k++){
			ret.push_back(mid[i][k]);
		}
	}
	ret.push_back(nodes[loop][node_id].children.size());
	return ret;
}

void func(){

	int adj_row,adj_col,group_index[2],boss_id,adj_boss_id;

	for(int loop = 0; loop <= 1; loop++){

		if(loop == 1){
			scanf("%d %d",&H,&W);
		}

		for(int row = 0; row < H; row++)scanf("%s",input[row]);

		//ダミーセルを敷く
		for(int row = 0; row <= H+1; row++){
			table[loop][row][0] = '.';
			table[loop][row][W+1] = '.';
		}
		for(int col = 0; col <= W+1; col++){
			table[loop][0][col] = '.';
			table[loop][H+1][col] = '.';
		}
		//転記
		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++)table[loop][row+1][col+1] = input[row][col];
		}
		//ダミーセルの分
		H += 2;
		W += 2;
		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++)used[row][col] = false;
		}

		for(int i = 0; i < H*W; i++){
			boss[i] = i;
			height[i] = 0;
		}

		group_index[loop] = 0;
		Type type;
		queue<Info> Q;

		//まず、連結しているセルをまとめる
		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				if(used[row][col])continue;

				if(table[loop][row][col] == '.'){
					type = WHITE;
				}else{
					type = BLACK;
				}
				used[row][col] = true;
				Q.push(Info(row,col));

				while(!Q.empty()){
					if(type == WHITE){

						for(int i = 0; i < 4; i++){
							adj_row = Q.front().row+diff_row_white[i];
							adj_col = Q.front().col+diff_col_white[i];

							if(rangeCheck(adj_row,adj_col) == false || table[loop][adj_row][adj_col] == '#' || used[adj_row][adj_col] == true)continue;

							used[adj_row][adj_col] = true;
							unite(get_index(Q.front().row,Q.front().col),get_index(adj_row,adj_col)); //unite

							Q.push(Info(adj_row,adj_col));
						}

					}else{

						for(int i = 0; i < 8; i++){
							adj_row = Q.front().row+diff_row_black[i];
							adj_col = Q.front().col+diff_col_black[i];

							if(rangeCheck(adj_row,adj_col) == false || table[loop][adj_row][adj_col] == '.' || used[adj_row][adj_col] == true)continue;

							used[adj_row][adj_col] = true;
							unite(get_index(Q.front().row,Q.front().col),get_index(adj_row,adj_col)); //unite

							Q.push(Info(adj_row,adj_col));
						}
					}
					Q.pop();
				}

				boss_id = get_boss(get_index(row,col)); //グループのボスを取得
				boss_index[boss_id] = group_index[loop]++; //出現順に変換
			}
		}

		//グループの隣接関係を計算
		for(int i = 0; i < group_index[loop]; i++){
			ADJ[i].clear();
			for(int k = 0; k < group_index[loop]; k++)is_adj[i][k] = false;
		}
		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++)used[row][col] = false;
		}

		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				if(used[row][col])continue;

				if(table[loop][row][col] == '.'){
					type = WHITE;
				}else{
					type = BLACK;
				}

				boss_id = get_boss(get_index(row,col)); //グループのボスを取得

				used[row][col] = true;
				Q.push(Info(row,col));

				while(!Q.empty()){
					if(type == WHITE){

						for(int i = 0; i < 4; i++){
							adj_row = Q.front().row+diff_row_white[i];
							adj_col = Q.front().col+diff_col_white[i];

							if(!rangeCheck(adj_row,adj_col))continue;

							if(table[loop][adj_row][adj_col] == '#'){
								adj_boss_id = get_boss(get_index(adj_row,adj_col));
								if(is_adj[boss_index[boss_id]][boss_index[adj_boss_id]])continue; //既知の情報
								is_adj[boss_index[boss_id]][boss_index[adj_boss_id]] = true;
								ADJ[boss_index[boss_id]].push_back(boss_index[adj_boss_id]);
								continue;
							}
							if(used[adj_row][adj_col])continue; //既に行った白マスならSKIP

							used[adj_row][adj_col] = true;

							Q.push(Info(adj_row,adj_col));
						}

					}else{

						for(int i = 0; i < 8; i++){
							adj_row = Q.front().row+diff_row_black[i];
							adj_col = Q.front().col+diff_col_black[i];

							if(!rangeCheck(adj_row,adj_col))continue;

							if(table[loop][adj_row][adj_col] == '.'){
								adj_boss_id = get_boss(get_index(adj_row,adj_col));
								if(is_adj[boss_index[boss_id]][boss_index[adj_boss_id]])continue; //既知の情報
								is_adj[boss_index[boss_id]][boss_index[adj_boss_id]] = true;
								ADJ[boss_index[boss_id]].push_back(boss_index[adj_boss_id]);
								continue;
							}
							if(used[adj_row][adj_col])continue; //既に行った黒マスならSKIP

							used[adj_row][adj_col] = true;

							Q.push(Info(adj_row,adj_col));
						}
					}
					Q.pop();
				}
			}
		}

		//木構造を作る
		for(int i = 0; i < group_index[loop]; i++)nodes[loop][i].children.clear();
		makeTree(loop,0,-1); //★★ダミーセルは必ず白であり、group 0であるはず★★

		RESULT[loop] = makeArray(loop,0);
	}

	if(RESULT[0].size() != RESULT[1].size()){
		printf("no\n");
	}else{

		for(int i = 0; i < RESULT[0].size(); i++){
			if(RESULT[0][i] != RESULT[1][i]){
				printf("no\n");
				return;
			}
		}
		printf("yes\n");
	}

}

int main(){

	while(true){
		scanf("%d %d",&H,&W);
		if(H == 0 && W == 0)break;

		func();
	}

	return 0;
}



Measured memory_bytes: 3884