题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3909

题意:给出两个矩阵A和B,找出最大的相同子矩阵S。输出S的高和宽以及在A和B中的位置。

思路:1、利用偏移量,其实就是枚举第二个矩阵跟第一个矩阵的那个位置开始对齐。再明白一点,就是,首先枚举B的(0,0)与A的哪个位置对齐;然后,枚举A的(0,0)与B的哪个位置对齐。这两个可以合并起来,偏移量范围为(-n2,-m2)-(n1,m1)。

2、然后就可以直接比较出对应位置的是不是相同。得到一个n2*m2的g矩阵,g[i][j]为0或者1。然后我们就是找这个g中最大的只包含1的子矩阵。我们一行一行处理,对于某一行i的某列j,我们用h[j]记录这列向上可匹配的长度,就是当前行的j列向上有连续的h[j]个1。然后,我们用l[j]和r[j]记录j列最左和最右匹配的长度。我们只需要从左向右扫描一遍就可求出l[i];然后从右向左扫描一遍就可求出r[j]数组。比如我们以计算l[j]为例。(1)对于当前的j,若j=0或者h[j-1]=0,那么left=j(left是一个临时变量);(2)若i=0(第一行)或者g[i-1][j]=0(上面一行为0),那么l[j]=left,因为这个l[j]是每行重复使用的,前面可能l[j]是记录的别的值,但是现在必须要置为当前的left,因为i=0和g[i-1][j]=0都等同于这是新的一行开始;(2)若left>l[j],l[j]=left。

3、从2的最后一句看出这个貌似是以h优先的。不妨设g的一种情况为

0 1 2 3 (列号)

0 0 1 1

1 1 1 1

1 1 1 1

显然最大是8.那么现在呢?我们转移完第一行后第二列的l为2,我们在2的最后一句是若left>l[j],l[j]=left。但是到达第二行是l[2]=0对吧,但是没有转移。此时求出的是6。但是这个程序并没有错。因为总有一个偏移量我们能够得到这个:

0 1 2 3 (列号)

1 1 1 1

1 1 1 1

此时就得到了8。所以,其实在一次中是以列优先的,也就是h。但是这并不会导致正确结果丢失,因为我们枚举的偏移量会覆盖每种情况。

int n1,m1,n2,m2;
char a[N][N],b[N][N];
int h[N],r[N],l[N],g[N][N];
int Max,X1,Y1,X2,Y2,rr,cc;

void deal(int ax,int ay)
{
    if(ax+n2<0||ay+m2<0) return; 
    clr(h,0);
    int i,j,k,left,right,n=n2,m=m2;
    FOR0(i,n) FOR0(j,m)
    {
        if(a[i+ax+50][j+ay+50]==b[i][j]) g[i][j]=1;
        else g[i][j]=0;
    }
    FOR0(i,n)
    {
        FOR0(j,m) g[i][j]?h[j]++:h[j]=0;
        FOR0(j,m) if(h[j])
        {
            if(!j||!h[j-1]) left=j;
            if(!i||!g[i-1][j]) l[j]=left;
            if(left>l[j]) l[j]=left;
        }
        FORL0(j,m-1) if(h[j])
        {
            if(j==m-1||!h[j+1]) right=j;
            if(!i||!g[i-1][j]) r[j]=right;
            if(right<r[j]) r[j]=right;
        }
        FOR0(j,m) if((r[j]-l[j]+1)*h[j]>Max)
        {
            Max=(r[j]-l[j]+1)*h[j];
            rr=h[j];
            cc=r[j]-l[j]+1;
            X1=i-h[j]+ax+1;
            Y1=l[j]+ay;
            X2=i-h[j]+1;
            Y2=l[j];
        }
    }
}

int main()
{
    Rush(n1)
    {
        RD(m1);
        int i,j;
        clr(a,0);
        for(i=50;i<n1+50;i++) RD(a[i]+50);
        RD(n2,m2);
        FOR0(i,n2) RD(b[i]);
        Max=0;
        for(i=-n2;i<n1;i++) for(j=-m2;j<m1;j++)
        {
            deal(i,j);
        }
        if(!Max) puts("0 0");
        else PR(rr,cc),PR(X1+1,Y1+1),PR(X2+1,Y2+1);
    }
    return 0;
}

ZOJ 3367 Counterfeit Money(最大相同子矩阵)的更多相关文章

  1. ZOJ 1074 最大子矩阵和

    Description Given a two-dimensional array of positive and negative integers, a sub-rectangle is any ...

  2. ZOJ 1074 To the Max(DP 最大子矩阵和)

    To the Max Time Limit: 2 Seconds      Memory Limit: 65536 KB Problem Given a two-dimensional array o ...

  3. 【转载】图论 500题——主要为hdu/poj/zoj

    转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...

  4. ZOJ 刷题记录 (。・ω・)ノ゙(Progress:31/50)

    [热烈庆祝ZOJ回归] P1002:简单的DFS #include <cstdio> #include <cstring> #include <algorithm> ...

  5. ZOJ 1859 Matrix Searching(二维线段树)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1859 Matrix Searching Time Limit: 10 Seco ...

  6. ACM 中 矩阵数据的预处理 && 求子矩阵元素和问题

            我们考虑一个$N\times M$的矩阵数据,若要对矩阵中的部分数据进行读取,比如求某个$a\times b$的子矩阵的元素和,通常我们可以想到$O(ab)$的遍历那个子矩阵,对它的各 ...

  7. ZOJ People Counting

    第十三届浙江省大学生程序设计竞赛 I 题, 一道模拟题. ZOJ  3944http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=394 ...

  8. ZOJ 3686 A Simple Tree Problem

    A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a rooted tree, each no ...

  9. [BZOJ1127][POI2008] KUP子矩阵

    Description 给一个n*n的地图,每个格子有一个价格,找一个矩形区域,使其价格总和位于[k,2k] Input 输入k n(n<2000)和一个n*n的地图 Output 输出矩形的左 ...

随机推荐

  1. 缓存应用--Memcached分布式缓存简介

    一.   什么是Memcached Memcached 是一个高性能的分布式内存 对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象 来减少读取数据库的次数,从而提供动态. ...

  2. IOS CoreData 多表查询demo解析

    在IOS CoreData中,多表查询上相对来说,没有SQL直观,但CoreData的功能还是可以完成相关操作的. 下面使用CoreData进行关系数据库的表与表之间的关系演示.生成CoreData和 ...

  3. c++11 lambda(匿名函数)

    #include <iostream> #include <functional> using namespace std::placeholders; //lambda即匿名 ...

  4. p3p之讲解

    P3P是一种被称为个人隐私安全平台项目(the Platform for Privacy Preferences)的标准,能够保护在线隐私权,使Internet冲浪者可以选择在浏览网页时,是否被第三方 ...

  5. asp.net @reqister指令

    @register指令通过声明将自定义 ASP.NET 服务器控件添加到页或用户控件中. 1.@register 指令有两种用法如下 <%@ Register tagprefix="t ...

  6. leetcode course shedule

    题目就不说了,问题本质就是在一个有向图中查找它是不是存在环. 上网百度了一下,方法是,找出图中入度为0 的点,将以它为起点的边去掉. 重复这一动作,直到所有的边都被去掉(没有环)或者存在边但是无法再去 ...

  7. JDK环境变量解析

    设置环境变量 在java 中需要设置三个环境变量(1.5之后不用再设置classpath了,但个人强烈建议继续设置以保证向下兼用问题)JDK安装完成之后我们来设置环境变量:右击“我的电脑”,选择“属性 ...

  8. ANDROID STUDIO, GRADLE AND NDK INTEGRATION

    Originally posted on:http://ph0b.com/android-studio-gradle-and-ndk-integration/ With the recent chan ...

  9. http://my.oschina.net/u/719192/blog/506062?p={{page}}

    http://my.oschina.net/u/719192/blog/506062?p={{page}}

  10. 2016网易实习生编程题:数组中两个数的和等于sum

    题目 找出数组中两个数的和等于sum的这两个数 解题 这个题目做过很多次了,利用HashMap,key为 sum-A[i] value为 i 当 加入HashMap时候A[i] 已经存在map中,ge ...