全是1的最大子矩阵

int maximalRectangle(vector<vector<char>>& matrix) {
    // 把R行C列的矩阵看作R个以第r行为底的直方图
    if (matrix.empty()) return 0;
    const int R = matrix.size(), C = matrix[0].size();
    int ans = 0;
    vector<int> h(C, 0);
    for (int r = 0; r < R; r++) {
        for (int c = 0; c < C; c++) {
            if (matrix[r][c] == '0') h[c] = 0;
            else h[c]++;
        }
        ans = max(ans, largestRectangleArea(h));
    }
    return ans;
}

int largestRectangleArea(vector<int>& h) {
    // 同https://leetcode.com/problems/largest-rectangle-in-histogram/
    // 找波峰,对应找下一个更小的数
    h.push_back(0); // 右哨兵
    const int N = h.size();
    int ans = 0;
    stack<int> stk; // 栈中保存坐标
    for (int i = 0; i < N; i++) {
        while (!stk.empty() && h[i] < h[stk.top()]) {
            int peak = stk.top(); stk.pop();
            int left = stk.empty() ? -1 : stk.top();
            ans = max(ans, h[peak] * (i - left - 1));
        }
        stk.push(i);
    }
    return ans;
}

全是1的子矩阵的个数

int numSubmat(vector<vector<int>>& mat) {
    // 把R行C列的矩阵看作R个以第r行为底的直方图
    if (mat.empty()) return 0;
    const int R = mat.size(), C = mat[0].size();
    int ans = 0;
    vector<int> h(C, 0);
    for (int r = 0; r < R; r++) {
        for (int c = 0; c < C; c++) {
            if (mat[r][c] == 0) h[c] = 0;
            else h[c]++;
        }
        ans += numSubmat(h);
    }
    return ans;
}

int numSubmat(vector<int>& h) { // 以第r行为底的直方图
    // 在直方图中统计全1子矩阵的个数
    // 找波峰,对应找下一个更小的数
    const int N = h.size();
    int ans = 0;
    vector<int> sum(N); // sum[i]保存右下角在(r,i)的子矩阵数
    stack<int> stk; // 保存下标
    for (int i = 0; i < N; i++) {
        while (!stk.empty() && h[i] <= h[stk.top()]) {
            stk.pop();
        }
        int lo = stk.empty() ? -1 : stk.top();
        // 现在h[lo]<h[i]
        // (lo..i]位置的高度>h[i],贡献右下角在(r,i)的子矩阵数(i-lo)*h[i]
        // (..lo]位置的高度<=h[i],贡献右下角在(r,i)的子矩阵数已记录在sum[lo]中
        sum[i] += (i - lo) * h[i];
        if (lo >= 0) sum[i] += sum[lo];
        ans += sum[i];

        stk.push(i);
    }
    return ans;
}

扩展:最大子矩阵和

参见:最大子段和

全是1的正方形子矩阵

int maximalSquare(vector<vector<char>>& matrix) {
    // 设dp[i][j]表示右下角在[i-1,j-1]的最大正方形子矩阵边长。
    // 当matrix[i-1][j-1]=='1'时,
    // dp[i][j] = 1 /*右下角的'1'*/ + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) /*即左、上、左上矩阵*/
    // 初始dp[0][..]=dp[..][0]=0
    if (matrix.empty()) return 0;
    const int M = matrix.size(), N = matrix[0].size();
    vector<vector<int>> dp(M + 1, vector<int>(N + 1, 0));
    int maxlen = 0;
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            if (matrix[i-1][j-1] == '1') {
                dp[i][j] = 1 + min({ dp[i-1][j-1], dp[i-1][j], dp[i][j-1] });
                maxlen = max(maxlen, dp[i][j]);
            }
        }
    }
    return maxlen * maxlen;
}

四边全为1的最大正方形

int largest1BorderedSquare(vector<vector<int>>& grid) {
    const int R = grid.size(), C = grid[0].size();
    // 辅助矩阵统计grid[i][j]往右、往下连续1的个数
    vector<vector<int>> right(R, vector<int>(C, 0));
    vector<vector<int>> down(R, vector<int>(C, 0));
    for (int r = R - 1; r >= 0; r--) {
        for (int c = C - 1; c >= 0; c--) {
            if (grid[r][c]) {
                right[r][c] = (c + 1 < C) ? right[r][c+1] + 1 : 1;
                down[r][c] = (r + 1 < R) ? down[r+1][c] + 1 : 1;
            }
        }
    }
    
    int maxLen = 0;
    for (int r = 0; r < R; r++) {
        for (int c = 0; c < C; c++) {
            for (int len = min(right[r][c], down[r][c]); len > maxLen; len--) {
                // 检查len是否可行
                if (right[r+len-1][c] >= len && down[r][c+len-1] >= len) {
                    maxLen = len;
                    break;
                }
            }
        }
    }
    return maxLen * maxLen;
}