【算法笔记】二维的哈希与迭代转换;Runtime Error 的解决思路

https://vjudge.net/problem/UVA-11019

如何对一个二维数组进行哈希

对于一个一维数组A(1*M),哈希的方式是:
s e e d M − 1 ∗ A 0 + s e e d M − 2 ∗ A 1 + s e e d M − 3 ∗ A 2 + . . . + s e e d 0 ∗ A M − 1 seed^{M-1}*A0 + seed^{M-2}*A1 + seed^{M-3}*A2+...+seed^{0}*AM-1 seedM−1∗A0+seedM−2∗A1+seedM−3∗A2+...+seed0∗AM−1

对于二维数组A(N*M)
s e e d 2 N − 1 ∗ h a s h ( 0 ) + s e e d 2 N − 2 ∗ h a s h ( 1 ) + s e e d 2 N − 3 ∗ h a s h ( 2 ) + . . . + s e e d 2 0 ∗ h a s h ( N − 1 ) seed2^{N-1}*hash(0) + seed2^{ N-2}*hash(1) + seed2^{N-3}*hash(2)+...+seed2^{0}*hash(N-1) seed2N−1∗hash(0)+seed2N−2∗hash(1)+seed2N−3∗hash(2)+...+seed20∗hash(N−1)

其中,hash(i)是第i行的哈希值

seed 的取法

seed 不需要是质数,只要大于A中的最大值就可以。想象对0~9组成的数组进行哈希,seed取10即可

同理,seed2 也不需要是质数,只需要是大于所有一维的哈希值即可

二维哈希的迭代

假设要哈希的是一个N*M的二维数组,把各项的seed1,seed2指数列出来:

M-1 N-1 M-2 N-1 M-3 N-1 ...1 N-1 0 N-1
M-1 N-2 M-2 N-2 M-3 N-2 ...1 N-2 0 N-2
M-1 N-3 M-2 N-3 M-3 N-3 ...1 N-3 0 N-3
M-1 ...1 M-2 ...1 M-3 ...1 ...1 ...1 0 ...1
M-1 0 M-2 0 M-3 0 ...1 0 0 0

横向

假如这个数组往右移:

del del M-1 N-1 M-2 N-1 M-3 N-1 ...1 N-1 0 N-1
del del M-1 N-2 M-2 N-2 M-3 N-2 ...1 N-2 0 N-2
del del M-1 N-3 M-2 N-3 M-3 N-3 ...1 N-3 0 N-3
del del M-1 ...1 M-2 ...1 M-3 ...1 ...1 ...1 0 ...1
del del M-1 0 M-2 0 M-3 0 ...1 0 0 0

规律:

  1. 第0列删掉
  2. 1~M-1列 seed1 指数加一
  3. 新增第M列,第M列的值是
0 N-1
0 N-2
0 N-3
0 ...1
0 0

如果预处理所有(N*1)的列,用上面的表算出他们的值,那么第3步就能解决了

巧合的是,第一步要删除的:

M-1 N-1
M-1 N-2
M-1 N-3
M-1 ...1
M-1 0

刚好是上面预处理的值的 s e e d 1 M − 1 seed1^{M-1} seed1M−1次

纵向

往下移:

del del del del del del del del del del
M-1 N-1 M-2 N-1 M-3 N-1 ...1 N-1 0 N-1
M-1 N-2 M-2 N-2 M-3 N-2 ...1 N-2 0 N-2
M-1 N-3 M-2 N-3 M-3 N-3 ...1 N-3 0 N-3
M-1 ...1 M-2 ...1 M-3 ...1 ...1 ...1 0 ...1
M-1 0 M-2 0 M-3 0 ...1 0 0 0

规律:

  1. 第0行删掉
  2. 1~N-1行 seed2 指数加一
  3. 新增第N列,第N列的值是

同上面横向移动的分析,我们需要预处理这样的一个值来完成 1 和 3 的操作

M-1 0 M-2 0 M-3 0 ...1 0 0 0

Runtime Error

心态真的会崩

RE 的原因一般是越界了,访问不存在的内存这样的,不过打出来所有访存的index,发现没有一个越界了

查了一下,也有可能是比方说数组开太大了,爆内存了,比如 int A1e8,肯定会 RE(栈内存里,堆内存不会)

我是进行过一个预处理的操作,然后把所有的数值存起来的,仔细想想这个数据量也挺大的

一个点15个case。每个case如果小块是1*1,大块是1000*1000,就要存 2e6 个数据。15*2e6=3e7,这个放栈内存上肯定爆掉,我用的vector,放堆内存不知道,估计也很极限,所以就给改成了每次用到的时候现算

后来查了vector其实极限能开1e9这样,上面的改动其实用不着,而且还给整的 TLE 了,因为其实算了两次

最后回家路上走着走着才想起来,把小块放在左上角的那步,就是迭代的初始情况,我没有加判断,比方说小块的大小比大块的还大,那第一步的时候是会越界的

加了

cpp 复制代码
        if(M==0 || N==0 || X==0 || Y==0){
            cout<<0<<endl;
            continue;
        }

        if(X>N || Y>M){
            cout<<0<<endl;
            continue;
        }

果然解决了

相关推荐
MC皮蛋侠客7 小时前
Google Test 单元测试指南
c++·单元测试·google test
艾莉丝努力练剑8 小时前
【Linux:文件】Ext系列文件系统进阶
linux·运维·服务器·c++·文件系统·文件io·ext
kkeeper~8 小时前
0基础C语言积跬步之数据在内存中的存储
c语言·数据结构·算法
wabs6669 小时前
关于贪心算法的一些自我总结【力扣45.跳跃游戏II】【灵感来源:代码随想录】
算法·贪心算法·复盘
2401_8769641310 小时前
【湖北专升本】2026湖北专升本真题PDF+备考资料汇总
数据结构·人工智能·经验分享·深度学习·算法·计算机视觉
basketball61610 小时前
C++ NULL 和 nullptr 区别 以及 nullptr 的核心实现
java·开发语言·c++
嗝o゚10 小时前
CANN GE 算子融合——融合算法与调度策略
算法·昇腾·cann·ge
小江的记录本10 小时前
【JVM虚拟机】垃圾回收GC:垃圾回收算法:标记-清除、标记-复制、标记-整理、分代收集(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·算法·安全·面试
Fre丸子_11 小时前
自定义文件夹选取功能
c++
Ulyanov12 小时前
用声明式语法重新定义Python桌面UI:QML+PySide6现代开发入门(一)
开发语言·python·算法·ui·系统仿真·雷达电子对抗仿真