https://nanti.jisuanke.com/t/42391
题意: 寻找两个矩阵的最大公共子矩阵
思路:
二维单调栈!分为A,B矩阵
横向:先预处理出B矩阵每一行每个格子在A矩阵中向右最多延伸多长。
纵向:知道了纵行每个格子向右的最大延伸,相当于求这个的最大公共矩阵(保证求的时候相连部分是能纵向相连的)
那么就是m次普通单调栈过程了。
solve()中我是记录了每个格子向左能延伸多长,再单调栈弹出的时候,再加上右边弹出部分的长度,保证这两个部分都不低于这个格子。但是这个写法wa17了
(要是找出了bug希望能告诉我,
我已经wa了50次了┭┮﹏┭┮)。
我tm一定是学了假单调栈。。。
solve2()是我看题解的写法,是通过记录下标来表示有多少格子不低于这个格子,同时不想连的时候,要把stk[0].i处理为i - 1,更新0这个点的位置。
AC代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e3 + 7;
int a[maxn][maxn],b[maxn][maxn];
int h[maxn][maxn];
int ans;
int n,m;
struct Node
{
int x,y;
}mp1[maxn * maxn + 100],mp2[maxn * maxn + 100];
struct STK
{
int l;
int h,i;
}stk[maxn];
void solve(int j)//递增单调栈
{
int top = 0;
stk[top].h = 0;stk[top].i = 0;
mp2[0].x = INF;mp2[0].y = INF;
h[n + 1][j] = 0;
int flag = 0;
for(int i = 0;i <= n + 1;i++)stk[i].l = 0;
for(int i = 1;i <= n + 1;i++)
{
if(mp1[b[i][j]].x == mp1[b[i - 1][j]].x + 1 && mp1[b[i][j]].y == mp1[b[i - 1][j]].y)
flag = 1;
else flag = 0;
int l = 0,len = 0;
while(top && (stk[top].h > h[i][j] || !flag))
{
int s = (stk[top].l + l + 1) * stk[top].h;
l += stk[top].l + 1;
ans = max(ans,s);
top--;
}
stk[++top].h = h[i][j];stk[top].i = i;
if(flag)stk[top].l = l;
else if(!flag)stk[top].l = 0;
}
}
void solve2(int j)
{
int top = 0;
stk[top].h = 0;stk[top].i = 0;
mp2[0].x = INF;mp2[0].y = INF;
h[n + 1][j] = 0;
int flag = 0;
for(int i = 0;i <= n + 1;i++)stk[i].l = 0;
for(int i = 1;i <= n + 1;i++)
{
if(mp1[b[i][j]].x == mp1[b[i - 1][j]].x + 1 && mp1[b[i][j]].y == mp1[b[i - 1][j]].y)
flag = 1;
else flag = 0;
while(top && (stk[top].h > h[i][j] || !flag))
{
int s = (i - 1 - stk[top - 1].i) * stk[top].h;
ans = max(ans,s);
top--;
}
stk[++top].h = h[i][j];stk[top].i = i;
if(!flag)stk[0].i = i - 1;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
scanf("%d",&a[i][j]);
mp1[a[i][j]].x = i;
mp1[a[i][j]].y = j;
}
}
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
scanf("%d",&b[i][j]);
mp2[b[i][j]].x = i;mp2[b[i][j]].y = j;
}
}
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
if(mp1[b[i][j]].x == mp1[b[i][j - 1]].x && mp1[b[i][j]].y == mp1[b[i][j - 1]].y + 1)
{
h[i][j] = h[i][j - 1] + 1;
}
else h[i][j] = 1;
}
}
for(int i = 1;i <= m;i++)
{
solve(i);
}
printf("%d\n",ans);
return 0;
}
BUG代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e3 + 7;
int a[maxn][maxn],b[maxn][maxn];
int h[maxn][maxn];
int ans;
int n,m;
struct Node
{
int x,y;
}mp1[maxn * maxn + 100],mp2[maxn * maxn + 100];
struct STK
{
int l;
int h,i;
}stk[maxn];
void solve(int j)//递增单调栈
{
int top = 0;
stk[top].h = 0;stk[top].i = 0;
mp2[0].x = INF;mp2[0].y = INF;
h[n + 1][j] = 0;
int flag = 0;
for(int i = 0;i <= n + 1;i++)stk[i].l = 0;
for(int i = 1;i <= n + 1;i++)
{
if(mp1[b[i][j]].x == mp1[b[i - 1][j]].x + 1 && mp1[b[i][j]].y == mp1[b[i - 1][j]].y)
flag = 1;
else flag = 0;
int l = 0,len = 0;
while(top && (stk[top].h > h[i][j] || !flag))
{
int s = (stk[top].l + l + 1) * stk[top].h;
l++;
ans = max(ans,s);
len = stk[top].l;
top--;
}
stk[++top].h = h[i][j];stk[top].i = i;
if(flag)stk[top].l = l + len;
else if(!flag)stk[top].l = 0;
}
}
void solve2(int j)
{
int top = 0;
stk[top].h = 0;stk[top].i = 0;
mp2[0].x = INF;mp2[0].y = INF;
h[n + 1][j] = 0;
int flag = 0;
for(int i = 0;i <= n + 1;i++)stk[i].l = 0;
for(int i = 1;i <= n + 1;i++)
{
if(mp1[b[i][j]].x == mp1[b[i - 1][j]].x + 1 && mp1[b[i][j]].y == mp1[b[i - 1][j]].y)
flag = 1;
else flag = 0;
while(top && (stk[top].h > h[i][j] || !flag))
{
int s = (i - 1 - stk[top - 1].i) * stk[top].h;
ans = max(ans,s);
top--;
}
stk[++top].h = h[i][j];stk[top].i = i;
if(!flag)stk[0].i = i - 1;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
scanf("%d",&a[i][j]);
mp1[a[i][j]].x = i;
mp1[a[i][j]].y = j;
}
}
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
scanf("%d",&b[i][j]);
mp2[b[i][j]].x = i;mp2[b[i][j]].y = j;
}
}
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
if(mp1[b[i][j]].x == mp1[b[i][j - 1]].x && mp1[b[i][j]].y == mp1[b[i][j - 1]].y + 1)
{
h[i][j] = h[i][j - 1] + 1;
}
else h[i][j] = 1;
}
}
for(int i = 1;i <= m;i++)
{
solve2(i);
}
printf("%d\n",ans);
return 0;
}