这题其实不难.
显然由w
构成的最大子矩形不可能大于把它完全变为x
后x
构成的最大子矩形,其它字符也是同理的,也就是说,最大的子矩形一定由x,y,z
中的某种字符构成.
我们可以枚举这三个字符,然后矩阵中的元素就只有两种了:可以变成当前这个字符(不妨记为1
),不能变成当前这个字符(不妨记为0
).
最终,问题转化为,求这个01矩阵中最大的只有1的子矩形.用单调栈可以在$O(nm)$的时间内求解(可以去第二章看看)
综上,问题在$O(nm)$的时间内解决.
/**********/省略快读
#define MAXN 1011
char str[MAXN][MAXN];
bool a[MAXN][MAXN];
ll up[MAXN][MAXN];
bool vaild(char cur,char t)//cur能否变成t
{
if(cur=='w')return t=='a'||t=='b';
if(cur=='x')return t=='b'||t=='c';
if(cur=='y')return t=='a'||t=='c';
if(cur=='z')return 1;
return cur==t;
}
ll n,m,ans;
ll s[MAXN],w[MAXN];//单调栈求解最大只有1的子矩形
void work(char t)//这一次都变成t
{
for(ll i=1;i<=n;++i)//先造出01矩形,顺便处理出up[i][j]表示(i,j)最多可以向上延伸多少个1
for(ll j=1;j<=m;++j)
{
a[i][j]=vaild(str[i][j],t);
up[i][j]=a[i][j]?up[i-1][j]+1:0;
}
ll top=0;
for(ll i=1;i<=n;++i)
{
for(ll j=1;j<=m;++j)
{
ll sum=0;
while(top&&s[top]>=up[i][j])
{
sum+=w[top];
umax(ans,s[top]*sum);
--top;
}
++sum;
s[++top]=up[i][j];w[top]=sum;
}
ll sum=0;
while(top)
{
sum+=w[top];
umax(ans,s[top]*sum);
--top;
}
}
}
int main()
{
while(scanf("%lld%lld",&n,&m)!=EOF)
{
ans=0;
for(ll i=1;i<=n;++i)scanf("%s",str[i]+1);
work('a');work('b');work('c');//枚举三个字符
printf("%lld\n",ans);
}
return 0;
}
这不讲了跟没讲一个样……重点都没说……
可参考这道题