哈希 字符串哈希模板

哈希:

维护一个集合,支持如下几种操作:

  1. I x,插入一个数 x;
  2. Q x,询问数 x 是否在集合中出现过;

现在要进行 N 次操作,对于每个询问操作输出对应的结果。

输入格式

第一行包含整数 N,表示操作数量。

接下来 N 行,每行包含一个操作指令,操作指令为 I xQ x 中的一种。

输出格式

对于每个询问指令 Q x,输出一个询问结果,如果 xx 在集合中出现过,则输出 Yes,否则输出 No

每个结果占一行。

数据范围

1≤N≤105
−109≤x≤109

输入样例:

5
I 1
I 2
I 3
Q 2
Q 5

输出样例:

Yes
No

哈希表:将一个范围很大的数映射成范围在(0, N) 的数
作用:
{
    1:插入一个数
    2:查找一个数
}

方法:
{
    1:开放寻址法
    2:拉链法
}

拉链法: 

//拉链法
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int N = 100003;//经验之谈:为减少冲突,找到大于N的第一个质数

int n;
int h[N], e[N], ne[N], idx;

void insert(int x)
{
    int k = (x % N + N) % N;
    e[idx] = x;
    ne[idx] = h[k];
    h[k] = idx;
    idx ++ ;
}

bool find(int x)
{
    int k = (x % N + N) % N;
    for (int i = h[k]; i != -1; i = ne[i])
    {
        if (e[i] == x) return true;
    }
    
    return false;
}

int main()
{
    int T;
    cin >> T;
    memset(h, -1, sizeof h);
    
    while (T -- )
    {
        int x;
        char op[2];
        scanf("%s", op);
        
        if (op[0] == 'I')
        {
            scanf("%d", &x);
            insert(x);
        }
        else
        {
            scanf("%d", &x);
            if (find(x)) puts("Yes");
            else puts("No");
        }
    }
    
    return 0;
}

开放寻址法:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int N = 200003, null = 0x3f3f3f3f;//经验之谈:为减少冲突,找到大于2 * N -- 3 * N的第一个质数

int h[N];

int find(int x)
{
    int k = (x % N + N) % N;
    while (h[k] != null && h[k] != x)//若这个坑位没人切要找的人不是他
    {
        k ++ ;
        if (k == N) k = 0;
    }
    
    return k;
}

int main()
{
    int T;
    cin >> T;
    memset(h, 0x3f, sizeof h);
    while (T -- )
    {
        int x;
        char op[2];
        scanf("%s %d", op, &x);
        
        int k = find(x);
        if (op[0] == 'I') h[k] = x;
        else 
        {
            if (h[k] != null) puts("Yes");
            else puts("No");
        }
    }
    
    return 0;
}

字符串哈希:

给定一个长度为 n 的字符串,再给定 m 个询问,每个询问包含四个整数 l1,r1,l2,r2请你判断[l1,r1] 和 [l2,r2] 这两个区间所包含的字符串子串是否完全相同。

字符串中只包含大小写英文字母和数字。

输入格式

第一行包含整数 n 和 m,表示字符串长度和询问次数。

第二行包含一个长度为 n 的字符串,字符串中只包含大小写英文字母和数字。

接下来 m 行,每行包含四个整数 l1,r1,l2,r2l,表示一次询问所涉及的两个区间。

注意,字符串的位置从 1 开始编号。

输出格式

对于每个询问输出一个结果,如果两个字符串子串完全相同则输出 Yes,否则输出 No

每个结果占一行。

数据范围

1≤n,m≤105

输入样例:

8 3
aabbaabb
1 3 5 7
1 3 6 8
1 2 1 2

输出样例:

Yes
No
Yes

解题思路:

字符串哈希:
{
    1:先预处理每个字符串哈希的前缀和;
    例如ABCD:
    则 h[1] = A, h[2] = AB, h[3] = ABC, h[4] = ABCD;
    2:将预处理的h[N]转化为P进制的整数对Q取余
    经验值:P(131, 13331), Q = 1 << 64冲突最小
    3:计算区间[l, r]字母是否相等即计算区间[l, r]哈希值是否相同
    即计算h[r] - h[l - 1] 的哈希值;
    先把h[l - 1]扩大到与r位数相同即h[l - 1] * p[r - l + 1];
    所以区间[l, r]的哈希值为h[r] - h[l - 1] * p[r - l + 1];

 代码:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace  std;

const int N = 100010, P = 131;

typedef unsigned long long ULL;//可以减少取模的操作

char str[N];
ULL h[N], p[N];

int get(int l, int r)
{
    return h[r] - h[l - 1] * p[r - l + 1];
}

int main()
{
    int n, m;
    cin >> n >> m;
    scanf("%s", str + 1);
    
    p[0] = 1;
    for (int i = 1; i <= n; i ++ )
    {
        h[i] = h[i - 1] * P + str[i];
        p[i] = p[i - 1] * P;
    }
    
    while (m -- )
    {
        int l1, r1, l2, r2;
        scanf("%d %d %d %d", &l1, &r1, &l2, &r2);
        {
            if (get(l1, r1) == get(l2, r2)) puts("Yes");
            else puts("No");
        }
    }
    
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个基本的字符串代码模板,使用了MurmurHash3算法: ```python import hashlib def murmur3_32(key, seed=0): """ MurmurHash3算法的32位版本 """ c1 = 0xcc9e2d51 c2 = 0x1b873593 r1 = 15 r2 = 13 m = 5 n = 0xe6546b64 hash_value = seed for i in range(0, len(key), 4): k = int.from_bytes(key[i:i+4], byteorder='little') k *= c1 k = (k << r1) | (k >> (32 - r1)) k *= c2 hash_value ^= k hash_value = ((hash_value << r2) | (hash_value >> (32 - r2))) * m + n remaining_bytes = len(key) % 4 if remaining_bytes == 3: hash_value ^= key[-remaining_bytes-1] << 16 hash_value ^= key[-remaining_bytes] << 8 hash_value ^= key[-1] hash_value *= c1 hash_value ^= hash_value >> 13 hash_value *= c2 hash_value ^= hash_value >> 15 elif remaining_bytes == 2: hash_value ^= key[-remaining_bytes] << 8 hash_value ^= key[-1] hash_value *= c1 hash_value ^= hash_value >> 13 hash_value *= c2 hash_value ^= hash_value >> 15 elif remaining_bytes == 1: hash_value ^= key[-1] hash_value *= c1 hash_value ^= hash_value >> 13 hash_value *= c2 hash_value ^= hash_value >> 15 hash_value ^= len(key) hash_value ^= hash_value >> 16 hash_value *= 0x85ebca6b hash_value ^= hash_value >> 13 hash_value *= 0xc2b2ae35 hash_value ^= hash_value >> 16 return hash_value class StringHash: def __init__(self, seed=0): self.seed = seed def hash(self, s): hash_value = murmur3_32(s.encode(), self.seed) return hash_value # example usage string_hash = StringHash(seed=42) hashed_value = string_hash.hash("hello world") print(hashed_value) ``` 在这个模板中,我们使用了MurmurHash3算法的32位版本来计算字符串的哈值。这个算法具有良好的散列性能和均匀性,适用于大多数哈表应用。我们还定义了一个StringHash类,它将字符串转换为哈值,并把这个哈值作为其内部状态之一。通过调用hash方法,可以对任意字符串进行哈计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥也不会hh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值