
本文共 2476 字,大约阅读时间需要 8 分钟。
hash函数
设字符集大小为 B B B,将所有字符编号为 0 , 1 , . . . , B − 1 0,1,...,B-1 0,1,...,B−1,则一个串可以看做一个 B B B进制数,以 B B B进制展开计算一个长 m m m的串 t t t的 h a s h hash hash值, P P P是一个大质数,减少碰撞次数
H a s h ( t ) = ∑ i = 0 m − 1 t i ⋅ B m − i + 1 m o d P Hash(t)=\sum_{i=0}^{m-1}{ t_i·B^{m-i+1}~mod~P} Hash(t)=∑i=0m−1ti⋅Bm−i+1 mod P
单模数哈希
ull base=131;int prime=233317;ull mod=212370440130137957LL;ull hash(char *s){ int len=strlen(s); ull ans=0; for(int i=0;i
自然溢出哈希
根据 u s i g n e d l o n g l o n g usigned~ ~long~~ long usigned long long自然溢出的性质优化(溢出自动取模)
ull base=131;ull hash(char *s){ int len=strlen(s); ull ans=0; for(int i=0;i
双哈希
更安全的做法是双哈希,翻车几率更低
ull base=131;ull mod1=19260817,mod2=19660813;ull hash1(char *s){ int len=strlen(s); ull ans=0; for(int i=0;i
hash函数的滚动性质
设 H ( s , l , r ) H(s,l,r) H(s,l,r)为串 s s s的子串 s l s l + 1 . . . s r s_ls_{l+1}...s_r slsl+1...sr的 h a s h hash hash值,则:
H ( s , l + 1 , r + 1 ) = ( H ( s , l , r ) − s l B r − l ) ⋅ B + S r + 1 H(s,l+1,r+1)=(H(s,l,r)-s_lB^{r-l})·B+S_{r+1} H(s,l+1,r+1)=(H(s,l,r)−slBr−l)⋅B+Sr+1

利用滚动性质,先 O ( m ) O(m) O(m)求出模式串 t t t的 h a s h hash hash值,然后 O ( n ) O(n) O(n)扫一遍文本串 s s s所有长 m m m的子串的 h a s h hash hash值,就可以找出匹配
ull base=131;int rabin_karp(char *t,char *s){ int n=strlen(s),m=strlen(t); if(n
动态维护子串hash
区间的 h a s h hash hash是可合并的,即如果知道了 H ( s , l , m i d ) H(s,l,mid) H(s,l,mid)和 H ( s , m i d + 1 , r ) H(s,mid+1,r) H(s,mid+1,r),则:
H ( s , l , r ) = ( H ( s , l , m i d ) ∗ B r − m i d + H ( s , m i d + 1 , r ) ) m o d P H(s,l,r)=(H(s,l,mid)*B^{r-mid}+H(s,mid+1,r))~mod~P H(s,l,r)=(H(s,l,mid)∗Br−mid+H(s,mid+1,r)) mod P
问题引入
维护子串的 h a s h hash hash值,有两种操作:
- 单点修改:可以将 s s s的某个字符修改为 c c c
- 区间查询:查询 s s s的子串 s l s l + 1 . . . s r s_ls_{l+1}...s_r slsl+1...sr的 h a s h hash hash值
ull base=131;char s[maxn];ull sgt[maxn*4],bn[maxn]; //bn[i]=base^ivoid build(int i,int l,int r){ if(l==r){ sgt[i]=s[l]-'a'; return; } int mid=(l+r)>>1,k=i<<1; build(k,l,mid); build(k|1,mid+1,r); sgt[i]=sgt[k]*bn[r-mid]+sgt[k|1];}ull query(int i,int l,int r,int x,int y){ if(x>1,k=i<<1; int len=max(0,max(r,y)-max(mid+1,x)+1); return query(k,l,mid,x,y)*bn[len]+query(k|1,mid+1,r,x,y);}void modify(int i,int l,int r,int pos,char x){ if(l==r){ sgt[i]=x-'a'; return; } int mid=(l+r)>>1,k=i<<1; if(pos<=mid) modify(k,l,mid,pos,x); else modify(k|1,mid+1,r,pos,x); sgt[i]=sgt[k]*bn[r-mid]+sgt[k|1];}
发表评论
最新留言
关于作者
