给出一个01矩阵,求次大的全1子矩阵。
求最大是经典的单调栈O(m*n)做法,但是求次大的时候就会出现各种麻烦。
算是成功签到了。
比起求最大,同时维护一个次大,但是这样会wa,还需要记录最大子矩阵宽高里最小的那一个,然后用最大子矩阵减去min(宽,高),这是为了考虑次大在最大内部的情况。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 5;
const int inf = maxn * maxn;
/*
4 5
11011
11111
10101
11111
*/
int n, m;
char s[maxn][maxn];
int maxArea = 0, maxArea2 = 0;
pair<int, int> kk;
void getMaxMartrixFromBottom(vector<int> height) {
vector<int> stack;
int i = 0;
for (; i < m; ++i) {
while (!stack.empty() && height[i] <= height[stack.back()]) {
int j = stack.back();
stack.pop_back();
int k = stack.empty() ? -1 : stack.back();
int curArea = (i - k - 1) * height[j];
//maxArea = Math.max(maxArea, curArea);
if (curArea >= maxArea) {
maxArea2 = maxArea;
maxArea = curArea;
kk = {(i - k - 1), height[j]};
} else if (curArea > maxArea2) {
maxArea2 = curArea;
}
}
stack.push_back(i);
}
while (!stack.empty()) {
int j = stack.back();
stack.pop_back();
int k = stack.empty() ? -1 : stack.back();
int curArea = (i - k - 1) * height[j];
//maxArea = Math.max(maxArea, curArea);
if (curArea >= maxArea) {
maxArea2 = maxArea;
maxArea = curArea;
kk = {(i - k - 1), height[j]};
} else if (curArea > maxArea2) {
maxArea2 = curArea;
}
}
}
void getMaxMartrix() {
vector<int> height(m + 5, 0);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
height[j] = s[i][j] == '0' ? 0 : height[j] + 1;
}
//maxArea = max(maxArea, getMaxMartrixFromBottom(height));
getMaxMartrixFromBottom(height);
}
}
int main() {
while (~scanf("%d%d", &n, &m)) {
maxArea = maxArea2 = 0;
for (int i = 0; i < n; ++i) {
scanf("%s", s[i]);
}
getMaxMartrix();
// maxArea2 = max(maxArea2, maxArea - min(kk.first, kk.second));
printf("%d\n", maxArea2);
}
return 0;
}