字符串哈希模板

字符串哈希

作用:快速查询子串,极快地比较两个字符串,以及还有其他用途。(比kmp泛用性更广)

原理:1. 将字符串的前缀和字符串数组想办法转换成数字;

​ 2.前缀和字符串数组转换为数字的方式,p进制转化十进制(秦九邵),“1234” ---> 1p0+2p1+3p^2+.....

​ 在这里使用ASCII 码作为基准数

​ 3.大的定义域映射到小集合,利用hash,取模2^64(利用unsigned long long 自然溢出)

​ 4.从哈希表中获取任意[l,r]这段hash值:h[r]-h[l]*p^(r-l+1) (左端向右端对齐后相减)

​ 5.131和13331 是经验数字作为进制P

https://www.acwing.com/problem/content/843/

#include <iostream>
#include <algorithm>

using namespace std;

typedef unsigned long long ULL; //0~2^64-1
const int N=100010,P=131; //131 or 13331

int n,m;
char str[N];
ULL h[N],p[N];

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

int main(){
    cin>>n>>m;
    cin>>str+1;
    p[0]=1;
    //make hashset base ASCII, p hex;

    for(int i=1;i<=n;i++){
        h[i]=h[i-1]*P+str[i]; //秦九邵
        p[i]=p[i-1]*P;   //save p^i
    }
    
    //matching
    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;
}

上一篇:.NET快速开发实践之应用IExtenderProvider实现控件焦点跳转


下一篇:洛谷 P5657 [CSP-S2019] 格雷码