题意:
一个由G或B组成的n*m的矩阵,现在可以任选任意行,将该行的G与B反转。求一个最大的全是G或B的正方形。 1 < = n , m < = 1000 1<=n,m<=1000 1<=n,m<=1000
题解:
预处理出
l
e
n
[
i
]
[
j
]
len[i][j]
len[i][j],表示以第
i
i
i行第
j
j
j列开始向后有
l
e
n
[
i
]
[
j
]
len[i][j]
len[i][j]个位置字母相同。
对于每一列可以自上而下处理出最上面的大于等于
l
e
n
[
i
]
[
j
]
len[i][j]
len[i][j]的
l
e
n
[
i
]
[
u
p
]
len[i][up]
len[i][up]。
同样也可以自下而上处理出最下面的大于等于
l
e
n
[
i
]
[
j
]
len[i][j]
len[i][j]的
l
e
n
[
i
]
[
d
o
w
n
]
len[i][down]
len[i][down]。
所以可以处理出宽度为
l
e
n
[
i
]
[
j
]
len[i][j]
len[i][j]的最大矩形的长为
u
p
−
d
o
w
n
+
1
up-down+1
up−down+1。
所以可以求出所有的最大正方形
总复杂度
O
(
n
2
)
O(n^2)
O(n2)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#define LL long long
#define inl inline
#define re register
#define MAXN 1010
using namespace std;
int n,m;
char s[MAXN][MAXN];
int len[MAXN][MAXN];
int up[MAXN],down[MAXN];
int stack[MAXN],ind;
int ans;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
{
len[i][m]=1;
for(int j=m-1;j>=1;j--)
if(s[i][j]!=s[i][j+1])len[i][j]=1;
else len[i][j]=len[i][j+1]+1;
}
for(int j=1;j<=m;j++)
{
ind=0;stack[0]=0;
for(int i=1;i<=n;i++)
{
while(len[stack[ind]][j]>=len[i][j])ind--;
up[i]=stack[ind]+1;
stack[++ind]=i;
}
ind=0;stack[0]=n+1;
for(int i=n;i>=1;i--)
{
while(len[stack[ind]][j]>=len[i][j])ind--;
down[i]=stack[ind]-1;
stack[++ind]=i;
}
for(int i=1;i<=n;i++)
{
int l=len[i][j],r=down[i]-up[i]+1;
ans=max(min(l,r)*min(l,r),ans);
}
}
printf("%d",ans);
return 0;
}