#include <bits/stdc++.h>
using namespace std;
const int NO_VALUE = -1;
const double PI = atan(1.0) * 4;
const int MAXRC = 55;
const vector<vector<int>> MOVES{{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
int R, C;
char grid[MAXRC][MAXRC];
bool visited[MAXRC][MAXRC];
vector<int> adjl[MAXRC * MAXRC];
struct Dot {
  int r, c;
  Dot(int row, int col) : r(row), c(col) {}
};
bool isUndirectedGraphCyclic(Dot d, Dot parent, char color) {
  visited[d.r][d.c] = true;
  for (int dir = 0; dir < MOVES.size(); dir++) {
    Dot nd(d.r + MOVES[dir][0], d.c + MOVES[dir][1]);
    if (nd.r == parent.r && nd.c == parent.c) {
      continue;
    }
    if (nd.r >= 0 && nd.r < R && nd.c >= 0 && nd.c < C &&
        grid[nd.r][nd.c] == color) {
      if (visited[nd.r][nd.c] || isUndirectedGraphCyclic(nd, d, color)) {
        return true;
      }
    }
  }
  return false;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cin >> R >> C;
  for (int i = 0; i < R; i++) {
    for (int j = 0; j < C; j++) {
      cin >> grid[i][j];
      visited[i][j] = false;
    }
  }
  for (int i = 0; i < R; i++) {
    for (int j = 0; j < C; j++) {
      if (!visited[i][j]) {
        if (isUndirectedGraphCyclic(Dot(i, j), Dot(NO_VALUE, NO_VALUE),
                                    grid[i][j])) {
          cout << "Yes\n";
          return 0;
        }
      }
    }
  }
  cout << "No\n";
  return 0;
}
