#include <bits/stdc++.h>
using namespace std;
struct SparseTable2D {
  int log2(int n) {
    int ans = 0;
    while (n >>= 1) ans++;
    return ans;
  }
  vector<vector<vector<vector<int>>>> T;
  SparseTable2D(vector<vector<int>> &M) {
    int n = M.size(), m = M[0].size();
    T.assign(log2(n) + 1,
             vector<vector<vector<int>>>(
                 n, vector<vector<int>>(log2(m) + 1, vector<int>(m))));
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < m; ++j) T[0][i][0][j] = M[i][j];
    for (int i = 0; i < n; ++i)
      for (int k = 1; (1 << k) <= m; ++k)
        for (int j = 0; j + (1 << k) <= m; ++j)
          T[0][i][k][j] =
              max(T[0][i][k - 1][j], T[0][i][k - 1][j + (1 << (k - 1))]);
    for (int k1 = 1; (1 << k1) <= n; ++k1)
      for (int i = 0; i + (1 << k1) <= n; ++i)
        for (int k2 = 0; (1 << k2) <= m; ++k2)
          for (int j = 0; j + (1 << k2) <= m; ++j)
            T[k1][i][k2][j] =
                max(T[k1 - 1][i][k2][j], T[k1 - 1][i + (1 << (k1 - 1))][k2][j]);
  }
  int query(int i1, int j1, int i2, int j2) {
    int k1 = log2(i2 - i1 + 1), k2 = log2(j2 - j1 + 1);
    int ans = max(T[k1][i1][k2][j1], T[k1][i2 - (1 << k1) + 1][k2][j1]);
    ans = max(ans, T[k1][i1][k2][j2 - (1 << k2) + 1]);
    return max(ans, T[k1][i2 - (1 << k1) + 1][k2][j2 - (1 << k2) + 1]);
  }
};
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<vector<bool>> M(n + 1, vector<bool>(m + 1));
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= m; ++j) {
      int a;
      cin >> a;
      M[i][j] = (a == 1);
    }
  vector<vector<int>> S(n + 1, vector<int>(m + 1, 0));
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= m; ++j)
      S[i][j] = S[i - 1][j] + S[i][j - 1] - S[i - 1][j - 1] + M[i][j];
  vector<vector<int>> MaxSquare(n + 1, vector<int>(m + 1));
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= m; ++j) {
      int left = -1, right = min(n - i, m - j);
      while (left != right) {
        int k = (left + right + 1) / 2;
        if (S[i + k][j + k] - S[i - 1][j + k] - S[i + k][j - 1] +
                S[i - 1][j - 1] ==
            (k + 1) * (k + 1))
          left = k;
        else
          right = k - 1;
      }
      MaxSquare[i][j] = (left + 1) * (right + 1);
    }
  SparseTable2D ST(MaxSquare);
  int t;
  cin >> t;
  while (t--) {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    int left = 0, right = min(x2 - x1 + 1, y2 - y1 + 1);
    while (left != right) {
      int k = (left + right + 1) / 2;
      if (ST.query(x1, y1, x2 - k + 1, y2 - k + 1) >= k * k)
        left = k;
      else
        right = k - 1;
    }
    cout << left << '\n';
  }
  return 0;
}
