題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2870
Largest Submatrix
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2835 Accepted Submission(s): 1373
思路:我的第一道單調棧題。之前看了白書上的例題,但不是特別理解,這次正好重新又學了一遍。
這道題和hdu1505十分相似,就是相當於統計三遍。也就是分別把矩陣中的w,x,y,z全轉成a,b,c。然後算三次。爲了計算方便,把字母矩陣換成01矩陣,見代碼。值得注意的是,經典的單調棧中每個元素的高度h[i]是一維的,而這題是二維的,用h[i][j]記錄即可,每一行都用一次單調棧即可,詳見代碼。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
char s[1010][1010];
int scopy[1010][1010];
int h[1010][1010];
int l[1010];
int r[1010];
int st[1010];
int n,m;
ll ans1;
ll ans2;
ll ans3;
ll solve1()
{
for(int i=1;i<=n;i++)
{
for(int j=0;j<m;j++)
{
if(s[i][j]=='a'||s[i][j]=='w'||s[i][j]=='y'||s[i][j]=='z')
{
scopy[i][j]=1;
}
else
{
scopy[i][j]=0;
}
if(scopy[i][j]==1)
{
h[i][j]=h[i-1][j]+1;
}
else
h[i][j]=0;
}
}
ans1=0;
int t;
for(int i=1;i<=n;i++)
{
t=0;
for(int j=0;j<m;j++)
{
while(t>0&&h[i][st[t-1]]>=h[i][j])
t--;
l[j]= t==0 ? 0 : (st[t-1]+1);
st[t++]=j;
}
t=0;
for(int j=m-1;j>=0;j--)
{
while(t>0&&h[i][st[t-1]]>=h[i][j])
t--;
r[j]= t==0 ? m : st[t-1];
st[t++]=j;
}
for(int j=0;j<m;j++)
ans1=max(ans1,(ll)(h[i][j]*(r[j]-l[j])));
}
return ans1;
}
ll solve2()
{
for(int i=1;i<=n;i++)
{
for(int j=0;j<m;j++)
{
if(s[i][j]=='b'||s[i][j]=='w'||s[i][j]=='x'||s[i][j]=='z')
{
scopy[i][j]=1;
}
else
{
scopy[i][j]=0;
}
if(scopy[i][j]==1)
{
h[i][j]=h[i-1][j]+1;
}
else
h[i][j]=0;
}
}
ans2=0;
int t;
for(int i=1;i<=n;i++)
{
t=0;
for(int j=0;j<m;j++)
{
while(t>0&&h[i][st[t-1]]>=h[i][j])
t--;
l[j]= t==0 ? 0 : (st[t-1]+1);
st[t++]=j;
}
t=0;
for(int j=m-1;j>=0;j--)
{
while(t>0&&h[i][st[t-1]]>=h[i][j])
t--;
r[j]= t==0 ? m : st[t-1];
st[t++]=j;
}
for(int j=0;j<m;j++)
ans2=max(ans2,(ll)(h[i][j]*(r[j]-l[j])));
}
return ans2;
}
ll solve3()
{
for(int i=1;i<=n;i++)
{
for(int j=0;j<m;j++)
{
if(s[i][j]=='c'||s[i][j]=='x'||s[i][j]=='y'||s[i][j]=='z')
{
scopy[i][j]=1;
}
else
{
scopy[i][j]=0;
}
if(scopy[i][j]==1)
{
h[i][j]=h[i-1][j]+1;
}
else
h[i][j]=0;
}
}
ans3=0;
int t;
for(int i=1;i<=n;i++)
{
t=0;
for(int j=0;j<m;j++)
{
while(t>0&&h[i][st[t-1]]>=h[i][j])
t--;
l[j]= t==0 ? 0 : (st[t-1]+1);
st[t++]=j;
}
t=0;
for(int j=m-1;j>=0;j--)
{
while(t>0&&h[i][st[t-1]]>=h[i][j])
t--;
r[j]= t==0 ? m : st[t-1];
st[t++]=j;
}
for(int j=0;j<m;j++)
ans3=max(ans3,(ll)(h[i][j]*(r[j]-l[j])));
}
return ans3;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
{
getchar();
scanf("%s",s[i]);
}
ll res=0;
ll t1=solve1();
ll t2=solve2();
ll t3=solve3();
res=max(t1,max(t2,t3));
printf("%lld\n",res);
}
return 0;
}