当前位置:网站首页>字符串哈希(2014 SERC J题)
字符串哈希(2014 SERC J题)
2022-08-09 20:51:00 【Here_SDUT】
概念
对于一个字符串s = c_{n-1}c_{n-2}…c_0,我们可以将其看成一个 p 进制数,其十进制表示形式x = c_{n-1} * p^{n-1} + c_{n-2} * p^{n-2} … + c_0 * p^0 ,用 x 来映射字符串 s ,通常 p = 131 或者 p = 13331 导致冲突的概率会最小,hash值 x 通常定义成 unsigned long long,让其自然溢出,达到 mod 2^{64}的目的。
下面给出字符串哈希的一些基本操作:
计算字符串s的哈希值:
unsigned long long Hash = 0, p = 131;
for(int i = 0; i < n; i++) {
Hash = Hash*p + s[i];
}
字符串s去掉最左端的字符,已知s的哈希值为Hash:
Hash = Hash - s[0] * pow(p,m-1);
例题
2014 SERC J The Big Painting
题意
给你两个图形 p 和 m ,大小分别为 h_pw_ph_mw_m让你在 m 中找一共有几个 p 图形。
分析
本题用到了二维hash,对于第一个小图案,先将每行看成一个字符串进行一次hash,然后将每行的hash值看成一个字符组成一列字符串再进行一次hash得到key值用来映射这个二维图形。同样地,在大图形中,用mp[i][j] 表示第 i 行第 j 个长度为 w_p 的字符串的hash值,然后用ha[i][j] 表示第 i 行第 j 个大小为 h_p * w_p 的图形的hash值。
代码
#include <bits/stdc++.h>
#define LL long long
#define ull unsigned long long
using namespace std;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
const double PI = acos(-1.0);
typedef pair<int, int> PII;
ull mp[2100][2100], key, pp[2100], p[2100], ha[2100][2100], p2[2100];
char s[2100][2100];
int main(int argc, char const *argv[]) {
int n, m, n2, m2;
char x;
cin >> n >> m >> n2 >> m2;
//预处理p1和p2的幂
p[0] = 1;
for (int i = 1; i <= 2010; i++) {
p[i] = p[i - 1] * 131;
}
p2[0] = 1;
for (int i = 1; i <= 2010; i++) {
p2[i] = p2[i - 1] * 13331;
}
//求小图案的hash值
for (int i = 1; i <= n; i++) {
getchar();
ull c = 0;
for (int j = 1; j <= m; j++) {
scanf("%c", &x);
c = c * p[1] + x;
}
key = key * p2[1] + c;
}
for (int i = 1; i <= n2; i++) {
getchar();
for (int j = 1; j <= m2; j++) scanf("%c", &s[i][j]);
}
//求每行的hash值
for (int i = 1; i <= n2; i++) {
for (int j = 1; j <= m2; j++) {
if (j <= m) {//前m个字符组成第一个字符串,放在mp[i][1]中国
mp[i][1] = mp[i][1] * p[1] + s[i][j];
} else {
mp[i][j - m + 1] =
mp[i][j - m] * p[1] + s[i][j] - s[i][j - m] * p[m];
}
}
}
//求二维hash
for (int i = 1; i <= m2; i++) {
for (int j = 1; j <= n2; j++) {
if (j <= n) {
ha[1][i] = ha[1][i] * p2[1] + mp[j][i];
} else {
ha[j - n + 1][i] =
ha[j - n][i] * p2[1] + mp[j][i] - mp[j - n][i] * p2[n];
}
}
}
LL res = 0;
for (int i = 1; i <= n2 - n + 1; i++) {
for (int j = 1; j <= m2 - m + 1; j++) {
if (ha[i][j] == key) res++;
}
}
cout << res;
return 0;
}
边栏推荐
猜你喜欢
CMake installation upgrade higher version
人人都可以DIY的大玩具,宏光MINIEV GAMEBOY产品力强,出行新装备
Excel如何打出正负号?Excel打出正负号的方法
Prometheus Operator 通过additional 添加target
Definition and Basic Operations of Sequence Tables
编程时请选择正确的输入法,严格区分中英文
matlab neural network ANN classification
【深度学习】pix2pix GAN理论及代码实现
What are the benefits of enterprise data integration?How do different industries solve the problem of data access?
Optimization of SQL Statements and Indexes
随机推荐
Next second data: the transformation of the modern data stack brought about by the integration of lake and warehouse has begun
How are data integration APIs key to enterprise digital transformation?
浅谈Numpy中的shape、reshape函数的区别
Win11搜索不到文件的解决方法
线性表的定义和基本操作
编程时请选择正确的输入法,严格区分中英文
FET Mosfet Leiditech corresponds to Infineon Infineon
基于模糊PID控制器的水温控制系统仿真
LED闪烁 闪灯芯片IC 手电筒IC 闪灯控制IC 闪烁IC流水灯
基于网络数据流的未知密码协议逆向分析
How to deal with keys when Redis is large?
智能家居设备安全分析技术综述
[Graphic and textual] How to reinstall Win7 system
蓝牙模块的分类和对应的属性特点
supervisor 命令操作大全「建议收藏」
痛击面试官 CURD系统也能做出技术含量
力扣383-赎金信——哈希映射数组法
字节二面问的MySQL,差点没答好
如何在WPF中设置Grid ColumnDefinitions的样式
Prometheus Operator 自定义监控添加redis explorer