Hash-open addressing method, zipper method and string prefix hash

Open addressing

Insert: Find the position where a number is placed through the find function. If it is not empty, check the next position until an empty position is found or the number already exists.
Search: If the number exists in the hash table, the index of the number will eventually be returned, otherwise the returned index will be empty.

#include <iostream>
#include <cstring>

using namespace std;

/*
为减少hash冲突,取模的数N应为质数
设null的值为1061109567,该数每一位都为0x3f,可用memset初始化
 */
const int N = 200003, null = 0x3f3f3f3f;
int h[N], 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()
{
    
    
    memset(h, 0x3f, sizeof(h));
    
    cin >> n;
    while (n--)
    {
    
    
        char op[2];
        int x;
        
        cin >> op >> x;
        
        if (op[0] == 'I') h[find(x)] = x; // 插入操作
        else  //查找操作 
            if (h[find(x)] == null) cout << "No" << endl;
            else cout << "Yes" << endl;

    } 
    return 0;
}

Zipper method

Idea: Put the data with the same value after hashing in the same linked list, and you only need to traverse the linked list when searching.
Insert: Get the pointer to the head node of the linked list through hash, and then insert the data by head interpolation.

#include <iostream>
#include <cstring>

using namespace std;

const int N = 100003;
int h[N], e[N], ne[N], idx; //h中存放第一个节点的索引, e存放数据域,ne存放指针域, idx代表当前使用到了第几个节点

void add(int x) // 等同于头插法
{
    
    
    int k = (x % N + N) % N;
    e[idx] = x;
    ne[idx] = h[k];
    h[k] = idx++;

}

bool find(int x)
{
    
    
    int k = (x % N + N) % N;
    for (int i = h[k]; i != -1; i = ne[i]) // 末节点的指针指向-1,代表链表遍历完毕
        if(e[i] == x) return true;
    return false;
}

int main()
{
    
    
    memset(h, -1, sizeof(h)); // 将所有值置为-1,代表各链表均为空

    int n;
    cin >> n;
    while (n--)
    {
    
    
        char op[2];
        int x;

        cin >> op >> x;

        if (op[0] == 'I') add(x); // 插入操作
        else //查找操作
            if(find(x)) cout << "Yes" << endl;
            else cout << "No" << endl;

    }
    return 0;
}

String prefix hashing

Idea: Think of a string as a number, and each character in the string represents one bit.

#include <iostream>

using namespace std;

typedef unsigned long long ULL; // 将hash值定为无符号长整形, 让其自动溢出, 相当于% 2^64
const int N = 100010, Q = 13331; // 为避免hash冲突, 将进制设置为131或13331
int h[N], q[N];

ULL get(int l, int r) // 获取截取子串哈希值
{
    
    
    return h[r] - h[l-1] * q[r-l+1];
}

int main()
{
    
    
    int n, m;
    char str[N];
    cin >> n >> m;
    scanf("%s", str + 1);

    q[0] = 1;
    for (int i = 1; i <= n; i++) // 初始化,q[i]的值为Q^(i-1),h[i]为前i个字符所组成子串的哈希值
    {
    
    
        q[i] = q[i-1] * Q;
        h[i] = h[i-1] * Q + str[i];
    }

    int l1, r1, l2, r2;
    for (int i = 0; i < m; i++)
    {
    
    
        cin >> l1 >> r1 >> l2 >> r2;

        if(get(l1, r1) == get(l2, r2)) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    
    return 0;
}

Guess you like

Origin blog.csdn.net/PBomb/article/details/107420661