// Проверяющая программа для задачи "Шахматный детектив"
// 7-ая Всероссийская Командная Олимпиада Школьников по Программированию
// Автор: Федор Царев
{$apptype console}
//{$o-,r+,q+}
{$o+,r-,q-}
uses
  sysutils, math, testlib;

type
  int = longint;

const
  maxn = 300;
  maxm = 300;
  black = 0;
  white = 1;
  grey = 2;

var
  n, m : int;
  pattern : array[0..maxn - 1, 0..maxn - 1] of int;
  f : array[-maxn..2 * maxn, -maxn..2 * maxn] of int;
  ja, pa : string;
  str : string;
  maxSq : array[-maxn..2 * maxn, -maxn..2 * maxn, 0..1] of int;

procedure checkForPattern();
var
  i, j : int;
begin
  for i := 0 to n - 1 do
  begin
    for j := 0 to m - 1 do
    begin
      if (pattern[i][j] = 2) then continue;
      if (pattern[i][j] <> f[i][j]) then
      begin
        quit(_wa, format('Participant answer does not match the pattern. pa[%d][%d] = %d, pattern[%d][%d] = %d', [i, j, f[i][j], i, j, pattern[i][j]]));
      end;
    end;
  end;
end;

procedure fillMaxSq();
var
  i, j, k : int;
  tmp : int;
begin
//  writeln('fill');
  for i := 2 * maxn downto -maxn do
  begin
    for j := 2 * maxn downto -maxn do
    begin
      maxSq[i][j][0] := 1;
      maxSq[i][j][1] := 1;
    end;
  end;
  for i := 2 * maxn - 1 downto -maxn do
  begin
    for j := 2 * maxn - 1 downto -maxn do
    begin
      for k := 0 to 1 do
      begin
        if (f[i][j] = 1 - k) then
        begin
          maxSq[i][j][k] := 0;
        end else begin
          tmp := 1000000000;
          if (i + 1 <= 2 * maxn) then tmp := min(tmp, maxSq[i + 1][j][k]);
          if (j + 1 <= 2 * maxn) then tmp := min(tmp, maxSq[i][j + 1][k]);
          if (i + 1 <= 2 * maxn) and (j + 1 <= 2 * maxn) then tmp := min(tmp, maxSq[i + 1][j + 1][k]);
          maxSq[i][j][k] := tmp + 1; 
        end;
      end;
    end;
  end;
end;

var
  haveBoard : array[-maxn..2 * maxn, -maxn..2 * maxn, 0..1] of boolean;
  ansBoard : array[-maxn..2 * maxn, -maxn..2 * maxn, 0..1] of boolean;

function canBoard(i, j, color, side : int) : boolean;
begin
  if (i >= n) or (j >= m) then
  begin
    result := true;
    exit;
  end;
  if (haveBoard[i][j][color]) then
  begin
    result := ansBoard[i][j][color];
    exit;
  end;
  result := (maxSq[i][j][color] >= side) and
            (canBoard(i + side, j, 1 - color, side)) and
            (canBoard(i, j + side, 1 - color, side));
  ansBoard[i][j][color] := result;
  haveBoard[i][j][color] := true; 
end;

function board(side : int) : boolean;
var
  i, j, k : int;
begin
  fillchar(ansBoard, sizeof(ansBoard), false);
  fillchar(haveBoard, sizeof(haveBoard), false);
  result := false;
  for i := -(side - 1) to 0 do
  begin
    for j := -(side - 1) to 0 do
    begin
      for k := 0 to 1 do
      begin
//        writeln(i, ' ', j, ' ', k);
        if (canBoard(i, j, k, side)) then
        begin
          result := true;
          exit;
        end;
      end;  
    end;
  end;  
end;

function getSide() : int;
var
  i, j : int;
begin
  result := 0;
  for i := 0 to m - 1 do
  begin
    j := i;
    while (j < m) and (f[0][i] = f[0][j]) do inc(j);
    result := max(result, j - i);
  end;
  for i := 0 to n - 1 do
  begin
    j := i;
    while (j < n) and (f[i][0] = f[j][0]) do inc(j);
    result := max(result, j - i);
  end;
end;

function checkForChessboard() : int;
var
  side : int;
  maxSide : int;
begin
  fillMaxSq();
//  maxSide := max(n, m);
//  for side := 1 to maxSide do
  side := getSide();
  begin
    if (board(side)) then
    begin
      result := side;
      exit;
    end;  
  end;
  result := -1;
end;

var
  i, j : int;
  ch : char;
  sideLen : int;

begin
  n := inf.readlongint();
  m := inf.readlongint();
  inf.readstring();

  ja := ans.readString();
  pa := ouf.readString();
  if (pa <> 'YES') and (pa <> 'NO') then
  begin
    quit(_pe, 'Not YES or NO (pa = ' + pa + ')');
  end;
  if (pa = 'NO') then
  begin
    if (ja = 'NO') then
    begin
      quit(_ok, format('Answer is NO. n = %d, m = %d', [n, m]));
    end;
    if (ja = 'YES') then
    begin
      quit(_wa, format('Jury has found the solution. Participant has not. n = %d, m = %d', [n, m]));
    end;
  end;

  for i := 1 to n do
  begin
    str := inf.readstring();
    for j := 1 to m do
    begin
      ch := str[j];
      if (ch = '.') then pattern[i - 1][j - 1] := 1;
      if (ch = '*') then pattern[i - 1][j - 1] := 0;
      if (ch = '?') then pattern[i - 1][j - 1] := 2;
    end;
  end;

  for i := -maxn to 2 * maxn do
  begin
    for j := -maxn to 2 * maxn do
    begin
      f[i][j] := grey;
    end;
  end;

  for i := 0 to n - 1 do
  begin
    str := ouf.readstring();
//    writeln(str);
    if (length(str) <> m) then
    begin
      quit(_wa, format('%d-th string of output has length not equal to m (len = %d, m = %d)', [i + 1, length(str), m]));
    end;
    for j := 0 to m - 1 do
    begin
      ch := str[j + 1];
      if not (ch in ['.', '*']) then
      begin
        quit(_wa, format('%d-th character of %d-th line is bad. ch = ', [j + 1, i + 1]) + ch);
      end;  
      if (ch = '.') then f[i][j] := 1;
      if (ch = '*') then f[i][j] := 0;
    end;
  end;

  checkForPattern();
  sideLen := checkForChessboard();

  if (sideLen = -1) and (pa = 'YES') then
  begin
    quit(_wa, 'pa = YES, but chessboard is badly constructed');
  end;

  if (sideLen <> -1) and (ja = 'NO') then
  begin
    quit(_fail, format('Participant has found the solution, but the jury has not (n = %d, m = %d)', [n, m]));
  end;

  quit(_ok, format('Answer is YES. n = %d, m = %d, side = %d', [n, m, sideLen]));

end.
