一、字符串Hash
实质:将字符串转化为数字形式
适用范围:字符串匹配
具体流程:
哈希函数
对于一个字符串可以将其化为以一个b(b>1)进制的数字,则一个字符串转化为哈希值为:选取两个合适的互素常数b,h(l<b<h),假设字符串C=c1c2c3...cm,定义哈希函数:H(C,k)=(c1*b^(m-1)+c2*b^(m-2)+...+cm*b^0)mod h(H(C,K)代表的是字符串从1-K这个位置的字符组成的子串转化为数字返回的哈希值)
滚动哈希
H(C,k+1)=H(C,k)*b+c(k+1)
对于一个字符串C=c1c2c4c4c5~cm,C的一个子串C’=C(k+1)C(k+1)C(k+2)~C(k+n),H(C')=H(C,k+n)-H(C,k)*b^n
代码:
#include<stdio.h> #include<stdlib.h> #include<iostream> #define FORa(i,s,e) for(LL i=s;i<=e;i++) #define FORs(i,s,e) for(LL i=s;i>=e;i--) using namespace std; typedef long long LL; const int N=1000000; LL m,n,T,b=27,ans; string s1,s2; LL pow[N+1],h[N+1]; int main() { scanf("%d",&T); pow[0]=1; FORa(i,1,N) pow[i]=pow[i-1]*b;//预处理出b^k(0<=k<N) while(T--) { cin>>s1>>s2; n=s1.size(),m=s2.size(),ans=0; FORa(i,1,m) h[i]=h[i-1]*b+LL(s2[i-1]-'A');//将前1-i位字符组成的字符串转化为哈希值 LL num_s=0; FORa(i,1,n) num_s=num_s*b+LL(s1[i-1]-'A');//计算出模式串的哈希值 FORa(i,1,m-n+1) if(num_s==h[i+n-1]-h[i-1]*pow[n])//枚举子串,检查 ans++; printf("%lld ",ans); } return 0; } /*1 BA BBABA 3 BAPC BAPC AZA AZAZAZA VERDI AVERDXIVYERDIAN */
二、哈希表
哈希函数的构造
- 除语法
- 乘积取整法
- 基数转换法
相关文章链接:
https://pks-loving.blog.luogu.org/zi-fu-chuan-xue-xi-bi-ji-ha-xi-hash-yu-zi-dian-shu-trie