#include <bits/stdc++.h>
using namespace std;
const int maxN = 55;
const int dir[4][2] = {-1, 0, 0, -1, 0, 1, 1, 0};
int N, M, _UP, root[maxN * maxN];
inline int _id(int x, int y) { return (x - 1) * M + y; }
char mp[maxN][maxN];
int fid(int x) { return x == root[x] ? x : root[x] = fid(root[x]); }
pair<int, int> it;
vector<pair<int, int>> vt[27];
inline bool In_map(int x, int y) {
  return x >= 1 && y >= 1 && x <= N && y <= M;
}
struct node {
  int x, y, step;
  node(int a = 0, int b = 0, int c = 0) : x(a), y(b), step(c) {}
};
queue<node> Q;
int vis[maxN][maxN] = {0};
bool check_OK(int sx, int sy, int xx, int yy) {
  if (sx == xx && abs(sy - yy) == 1) {
    if (mp[sx][sy] == mp[xx][yy] && abs(vis[sx][sy] - vis[xx][yy]) >= 3)
      return true;
  } else if (sy == yy && abs(xx - sx) == 1) {
    if (mp[sx][sy] == mp[xx][yy] && abs(vis[sx][sy] - vis[xx][yy]) >= 3)
      return true;
  }
  return false;
}
bool OK = false;
int SX, SY;
void dfs(int sx, int sy, int deep) {
  for (int i = 0, xx, yy; i < 4; i++) {
    xx = sx + dir[i][0];
    yy = sy + dir[i][1];
    if (!In_map(xx, yy)) continue;
    if (mp[sx][sy] ^ mp[xx][yy]) continue;
    if (vis[xx][yy]) {
      if (check_OK(sx, sy, xx, yy)) {
        OK = true;
        return;
      }
      continue;
    }
    vis[xx][yy] = deep + 1;
    dfs(xx, yy, deep + 1);
    if (OK) return;
  }
}
int main() {
  scanf("%d%d", &N, &M);
  _UP = N * M;
  for (int i = 1; i <= _UP; i++) root[i] = i;
  for (int i = 1, col; i <= N; i++) {
    scanf("%s", mp[i] + 1);
    for (int j = 1; j <= M; j++) {
      col = mp[i][j] - 'A';
      vt[col].push_back(make_pair(i, j));
    }
  }
  for (int i = 0, len; i < 26; i++) {
    len = (int)vt[i].size();
    for (int j = 0; j < len; j++) {
      it = vt[i][j];
      if (vis[it.first][it.second]) continue;
      SX = it.first;
      SY = it.second;
      vis[SX][SY] = 1;
      dfs(it.first, it.second, 1);
      if (OK) {
        printf("Yes\n");
        return 0;
      }
    }
  }
  printf("No\n");
  return 0;
}
