专栏文章
10.11 Hash进阶-回文串
算法·理论参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minmllel
- 此快照首次捕获于
- 2025/12/02 04:52 3 个月前
- 此快照最后确认于
- 2025/12/02 04:52 3 个月前
Hash进阶操作
Hash基础:9.27 字符串哈希-Hash
Hash进阶求回文串需要在从左到右求Hash值的同时从右到左在求一边Hash值最后对比从左到右和从右到左是否相等,如果相等就是回文
求Hash函数
依然使用进制求法
从左到右
CPP for(int i(1);i<=n;i++){
hs1[i]=hs1[i-1]*p+s[i];
}
从右到左
CPP for(int i(n);i>0;i--){
hs2[i]=hs2[i+1]*p+s[i];
}
计算区间[l,r]的Hash值
从左到右
注意到因为储存的使字符串前i个字符的Hash值,所以我们可以把Hash数组当作一个前缀和数组来看待
[l,r]的Hash值=
但Hash值是一个p进制的数,而不是前缀和,举个十进制数的例子:
要取怎么办?
如果只是像前缀和一样直接减去的话就成了很明显不对,应该是,这样才能求出,将这个式子转换一下就成了,而指数很明显就是的长度
现在我们回到Hash上,答案显而易见:
[l,r]的Hash值=
CPPull get_hash1(int l,int r){
return hs1[r]-hs1[l-1]*pw[r-l+1];
}
从右到左
在考虑如何截取区间的Hash值前我们先模拟一下Hash数组的形成
当字符串为时
即
很明显原来的公式不对了如果使用减法就成负数了,既然不好想那我们又来举个例子:
如果我们要从中取出怎么办?
可以发现的Hash值在中出现了只是多了一个这时我们发现,所以我们只需要将减去,而这时候我们又发现中的指数与从左到右的意思相同,即需要取的长度,所以公式是:
[l,r]的Hash值=
CPPull get_hash2(int l,int r){
return hs2[l]-hs2[r+1]*pw[r-l+1];
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...