#include <bits/stdc++.h>
using namespace std;
inline void pisz(int n) { printf("%d\n", n); }
template <typename T, typename TT>
ostream &operator<<(ostream &s, pair<T, TT> t) {
  return s << "(" << t.first << "," << t.second << ")";
}
template <typename T>
ostream &operator<<(ostream &s, vector<T> t) {
  for (int(i) = 0; (i) < (((int)(t.size()))); ++(i)) s << t[i] << " ";
  return s;
}
struct UnionFind {
  vector<int> tab, ile;
  UnionFind(int n) : tab(n), ile(n, 1) {
    for (int(i) = 0; (i) < (n); ++(i)) tab[i] = i;
  }
  int find(int a) {
    if (tab[a] == a) return a;
    int fa = find(tab[a]);
    return tab[a] = fa;
  }
  bool unia(int a, int b) {
    int fa = find(a), fb = find(b);
    if (fa == fb) return 0;
    if (ile[fa] <= ile[fb]) {
      ile[fb] += ile[fa];
      tab[fa] = fb;
    } else {
      ile[fa] += ile[fb];
      tab[fb] = fa;
    }
    return 1;
  }
};
char s[1024][1024];
vector<pair<int, int> > neighs[1000006];
int temp[1024][1024];
int n, m;
void dfs(int x, int y) {
  if (temp[x][y] != 1) return;
  temp[x][y] = 2;
  int dx[] = {0, 0, -1, 1}, dy[] = {-1, 1, 0, 0};
  for (int(u) = 0; (u) < (4); ++(u)) {
    int x1 = x + dx[u], y1 = y + dy[u];
    if ((x1 >= 0 && x1 < n && y1 >= 0 && y1 < m)) dfs(x1, y1);
  }
}
bool isConnectedAndEveryPointHasTwoNeighbours(
    const vector<pair<int, int> > &st) {
  for (int(i) = 0; (i) < (((int)(st.size()))); ++(i))
    temp[st[i].first][st[i].second] = 1;
  dfs(st[0].first, st[0].second);
  bool wrong = 0;
  for (int(i) = 0; (i) < (((int)(st.size()))); ++(i)) {
    if (temp[st[i].first][st[i].second] != 2) wrong = 1;
    int dx[] = {0, 0, -1, 1}, dy[] = {-1, 1, 0, 0}, cnt = 0;
    for (int(u) = 0; (u) < (4); ++(u)) {
      int x = st[i].first + dx[u], y = st[i].second + dy[u];
      if ((x >= 0 && x < n && y >= 0 && y < m) && temp[x][y] == 2) ++cnt;
    }
    if (cnt != 2) wrong = 1;
  }
  for (int(i) = 0; (i) < (((int)(st.size()))); ++(i))
    temp[st[i].first][st[i].second] = 0;
  return !wrong;
}
inline int c(int x, int y) { return x * m + y; }
int main() {
  for (int(i) = 0; (i) < (1024); ++(i))
    for (int(j) = 0; (j) < (1024); ++(j)) temp[i][j] = 0;
  scanf("%d %d", &n, &m);
  for (int(i) = 0; (i) < (n); ++(i)) scanf("%s", s[i]);
  int res = 0;
  for (int(i) = 0; (i) < (n - 1); ++(i))
    for (int(j) = 0; (j) < (m - 1); ++(j)) {
      if (s[i][j] == '1' && s[i + 1][j] == '1' && s[i][j + 1] == '1' &&
          s[i + 1][j + 1] == '1')
        res = 4;
    }
  UnionFind uf0(n * m);
  for (int(i) = 0; (i) < (n); ++(i))
    for (int(j) = 0; (j) < (m); ++(j))
      if (s[i][j] == '0') {
        if (i < n - 1)
          if (s[i + 1][j] == '0') uf0.unia(c(i, j), c(i + 1, j));
        if (j < m - 1)
          if (s[i][j + 1] == '0') uf0.unia(c(i, j), c(i, j + 1));
        if (i < n - 1 && j < m - 1)
          if (s[i + 1][j + 1] == '0') uf0.unia(c(i, j), c(i + 1, j + 1));
        if (i > 0 && j < m - 1)
          if (s[i - 1][j + 1] == '0') uf0.unia(c(i, j), c(i - 1, j + 1));
      }
  vector<bool> hasborder(1000006, 0);
  int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1}, dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
  for (int(i) = 0; (i) < (n); ++(i))
    for (int(j) = 0; (j) < (m); ++(j))
      if (s[i][j] == '0') {
        int k = uf0.find(c(i, j));
        if (hasborder[k]) continue;
        for (int(u) = 0; (u) < (8); ++(u)) {
          const int x = i + dx[u], y = j + dy[u];
          if (!(x >= 0 && x < n && y >= 0 && y < m)) {
            hasborder[k] = 1;
            break;
          }
          if (s[x][y] == '1') neighs[k].push_back(make_pair(x, y));
        }
      }
  for (int(i) = 0; (i) < (n); ++(i))
    for (int(j) = 0; (j) < (m); ++(j))
      if (s[i][j] == '0')
        if (uf0.find(c(i, j)) == c(i, j)) {
          int k = c(i, j);
          if (hasborder[k]) continue;
          sort(neighs[k].begin(), neighs[k].end());
          vector<pair<int, int> > uniq;
          for (int(f) = 0; (f) < (((int)(neighs[k].size()))); ++(f)) {
            if (uniq.empty() || uniq.back() != neighs[k][f]) {
              uniq.push_back(neighs[k][f]);
            }
          }
          if (isConnectedAndEveryPointHasTwoNeighbours(uniq))
            res = max(res, ((int)(uniq.size())));
        }
  pisz(res);
}
