散列表

哈希表

我用的拉链法。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;
int N = 100003;
vector<int> H[100003];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    char op;
    int v;
    int x;
    //主要难点:负数modN之后还是负数,需要(v%N+N)%N,两次%N是为了照顾正数
    while (n -- ){
        cin >> op;
        
        if(op=='I'){
            cin >> v;
            H[(v%N+N)%N].push_back(v);
        }
        else if(op=='Q'){
            cin >> v;
            x = (v%N+N)%N;
            int flag=0;
            for (int i = 0; i < H[x].size(); i ++ ){
                if(H[x][i]==v){
                    flag=1;
                    break;
                }
            }
            cout << (flag?"Yes":"No") <<endl;
        }
    }
    return 0;
}

字符串哈希

这个比较厉害,其实就是把字符转为了系数,然后字符串的哈希就是一个多项式

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

typedef unsigned long long ULL;
ULL h[100100];
ULL p[100100];
int BASE=103;
string s;
int main()
{
    int n,m,a,b,c,d;
    cin >> n >> m;
    cin >> s;
    s = " "+s;
    p[0]=1;
    h[0]=1;
    for (int i = 1; i <= n; i ++ ){
        p[i] = p[i-1]*BASE;
        h[i] = h[i-1]*BASE+s[i];
    }
    while (m -- ){
        cin >> a >> b >> c>> d;
        cout << (h[b]-h[a-1]*p[b-a+1]==h[d]-h[c-1]*p[d-c+1]?"Yes":"No")<<endl; 
    }
}

例子很好理解,最早出现的字符,次数最高,需要通过乘以p来消除。

例子

我们用字母直接表示哈希计算过程,更清晰地展示公式原理。以字符串 "abcabc" 为例,取区间 [2,3] 和 [5,6](子串都是 "bc"),用 B 代表 BASE(基数)。

1. 定义字符与前缀哈希

  • 字符串下标从1开始:s[1]=as[2]=bs[3]=cs[4]=as[5]=bs[6]=c
  • 前缀哈希 h[i] 定义:前i个字符的哈希值,计算规则为 h[i] = h[i-1]×B + s[i]

2. 计算前缀哈希(字母表示)

h[1] = a (仅第一个字符a)

h[2] = h[1]×B + s[2] = a×B + b (前2个字符"ab"的哈希)

h[3] = h[2]×B + s[3] = (a×B + b)×B + c = a×B² + b×B + c (前3个字符"abc"的哈希)

h[4] = h[3]×B + s[4] = (a×B² + b×B + c)×B + a = a×B³ + b×B² + c×B + a (前4个字符"abca"的哈希)

h[5] = h[4]×B + s[5] = (a×B³ + b×B² + c×B + a)×B + b = a×B⁴ + b×B³ + c×B² + a×B + b (前5个字符"abcab"的哈希)

h[6] = h[5]×B + s[6] = (a×B⁴ + b×B³ + c×B² + a×B + b)×B + c = a×B⁵ + b×B⁴ + c×B³ + a×B² + b×B + c (前6个字符"abcabc"的哈希)

3. 计算 [2,3] 子串的哈希("bc")

公式:子串[l,r]的哈希 = h[r] - h[l-1]×B^(r-l+1)
这里 l=2r=3r-l+1=2,所以:

哈希值 = h[3] - h[1]×B²
= (a×B² + b×B + c) - (a)×B²
= a×B² + b×B + c - a×B²
= b×B + c (正好是"bc"的哈希:b×B + c)

4. 计算 [5,6] 子串的哈希("bc")

这里 l=5r=6r-l+1=2,所以:

哈希值 = h[6] - h[4]×B²
= (a×B⁵ + b×B⁴ + c×B³ + a×B² + b×B + c) - (a×B³ + b×B² + c×B + a)×B²
= a×B⁵ + b×B⁴ + c×B³ + a×B² + b×B + c - (a×B⁵ + b×B⁴ + c×B³ + a×B²)
= b×B + c (同样是"bc"的哈希:b×B + c)

结论

两个子串 "bc" 的哈希值均为 b×B + c,因此哈希值相等,判断为相同子串。这直接体现了公式的正确性:相同的子串通过哈希公式计算后,必然得到相同的哈希值

posted @ 2025-08-02 20:54  .N1nEmAn  阅读(9)  评论(0)    收藏  举报