#include <bits/stdc++.h>
using namespace std;
const long long INF = 1000000000000000000LL;
const int IINF = 1000000000;
const int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
const int dv[] = {0, 1, 0, 1, 1, 0, 1, 0};
const int MAXN = 1000, MAXM = 1000, CD = 8;
int N, M;
bool on[MAXM][MAXN];
int edgeSeen[MAXM][MAXN];
int edgeArea[MAXM][MAXN];
int cellArea[MAXM][MAXN];
int cAreas;
vector<pair<int, int> > edges[MAXN * MAXM];
int bestArea = 0;
char buf[MAXM + 1];
int main() {
  ;
  ;
  for (int i = (0); i < (CD); i++) {
    assert(dx[i] == -dx[CD - 1 - i]);
    assert(dy[i] == -dy[CD - 1 - i]);
  }
  scanf("%d %d", &N, &M);
  for (int y = (0); y < (N); y++) {
    scanf("%s", buf);
    for (int x = (0); x < (M); x++) {
      on[x][y] = buf[x] == '1';
    }
  }
  for (int x = (0); x < (M - 1); x++) {
    for (int y = (0); y < (N - 1); y++) {
      if (on[x][y] && on[x][y + 1] && on[x + 1][y] && on[x + 1][y + 1]) {
        bestArea = 4;
        break;
      }
    }
  }
  memset(cellArea, -1, sizeof(cellArea));
  memset(edgeArea, -1, sizeof(edgeArea));
  memset(edgeSeen, -1, sizeof(edgeSeen));
  for (int x = (0); x < (M); x++) {
    for (int y = (0); y < (N); y++) {
      if (!on[x][y] && cellArea[x][y] < 0) {
        cellArea[x][y] = cAreas;
        queue<pair<int, int> > q;
        q.push(pair<int, int>(x, y));
        bool ok = true;
        while (!q.empty()) {
          pair<int, int> p = q.front();
          q.pop();
          for (int i = (0); i < (CD); i++) {
            pair<int, int> np(p.first + dx[i], p.second + dy[i]);
            if (0 <= np.first && np.first < M && 0 <= np.second &&
                np.second < N) {
              if (on[np.first][np.second]) {
                int& ea = edgeArea[np.first][np.second];
                if (ea != cAreas) {
                  ea = cAreas;
                  edges[cAreas].push_back(np);
                }
              } else if (cellArea[np.first][np.second] < 0) {
                cellArea[np.first][np.second] = cAreas;
                q.push(np);
              }
            } else {
              ok = false;
              break;
            }
          }
        }
        if (ok && edges[cAreas].size() > bestArea) {
          assert(!edges[cAreas].empty());
          pair<int, int> ep = edges[cAreas].front();
          int lt = -1;
          while (edgeSeen[ep.first][ep.second] != cAreas) {
            edgeSeen[ep.first][ep.second] = cAreas;
            int got = 0;
            pair<int, int> nep;
            int nlt;
            for (int i = (0); i < (CD); i++) {
              if (dv[i]) {
                pair<int, int> np(ep.first + dx[i], ep.second + dy[i]);
                if (0 <= np.first && np.first < M && 0 <= np.second &&
                    np.second < N && edgeArea[np.first][np.second] == cAreas) {
                  got++;
                  if (i != CD - 1 - lt) {
                    nep = np;
                    nlt = i;
                  }
                }
              }
            }
            if (got != 2) {
              ok = false;
              break;
            }
            ep = nep;
            lt = nlt;
          }
          if (ok) {
            for (__typeof((edges[cAreas]).begin()) it = (edges[cAreas]).begin();
                 it != (edges[cAreas]).end(); it++) {
              if (edgeSeen[it->first][it->second] != cAreas) {
                ok = false;
                break;
              }
            }
            if (ok) {
              bestArea = edges[cAreas].size();
            }
          }
        }
        cAreas++;
      }
    }
  }
  printf("%d\n", bestArea);
  return 0;
}
