18908 字符串哈希

18908 字符串哈希

时间限制:1000MS  代码长度限制:10KB
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC

Description

(1)这一段是乱七八糟的教学模块,看不清楚就百度吧。
字符串哈希可以用于快速比较两个字符串是否相等,或者快速找到子串t在主串s中的位置(模式匹配)。
在完成预处理之后,比较任意两个字符串相等的复杂度O(1)。模式匹配的复杂度和kmp算法接近,为O(n+m)。
那么如何为字符串设计哈希函数呢?
最简单的方法:把字符串直接映射为整数比如abcd看成1234,ccbb看成是3322,考虑到字符串的长度,这样的哈希函数显然不可行。
在前一种设计的基础上,一种容易想到的哈希法是求和,比如f(abcd)=1+2+3+4=10,f(ccbb)=3+3+2+2=10。但这样设计哈希函数非常容易冲突。
通用的方法,取一固定值P,把字符串看作P进制数,并分配一个大于0的数值,代表每种字符。
一般来说,我们分配的数值都远小于P。例如,对于小写字母构成的字符串,可以令a = 1 , b = 2 , . . . , z = 26 。 取一固定值M,求出该P进制数对M的余数,作为该字符串的Hash值。
这样f(abcd)=1*p^3+2*p2+3*p+4,f(ccbb)=3*p^3+3*p2+2*p+2。这种方法如果两个字符串不相同,他们的哈希值相同的概率极小。
当然,这样的哈希函数,应该很容易想到的问题是字符串哈希函数的值很容易就会超过int范围。
此处的技巧是,如果我们不给定余数M的话,超过2^32的部分因为超过了int范围,会自动舍掉(相当于对2^32取余).

稳妥起见,字符串哈希一般采用unsigned long long 类型。
在比较多个字符串是否存在两个相等字符串时,可以采用上述方法求出每个字符串的哈希值,再看看是否有相同值。
在作子串处理或模式匹配问题时,我们需要快速找到子串的哈希值,一般是采用数组的方式来处理。
在字符串哈希数组里,通过一个简单的公式计算就能得到子串的哈希值。

思路记录:字符串哈希,说白了就是用一个更大的进制数来代替原有的字母,因为是为了防止哈希冲突,我们必须要用足够大的数据进制(起码比26大)去代替,小的话很容易产生哈希冲突,这题目数据比较小,26进制也能过,不过一般是取131,1331,13331这些数。判断两个区间的哈希码是否相同即可判断两个区间的字符串是否相等,因为哈希码很大,默认用long long 去纯的话其实是会溢出(即存放的是模运算后的结果),为了可以快速去计算两个区间哈希码,可以运用前缀和(感觉更像前缀积,差不多就这个意思)的思想,就是比如说输入的字符串是“abcdefg”,在计算的过程中也可以把a,ab,abc,abcd,abcdef,abcdefg的哈希码全部计算出来,后面比如说要求cd的哈希码就是通过abcd和ab之间的关系求出哈希码,达到快速运算的效果,因为区间之间的距离可能很大,所以得提前算一下距离之间的积用p数组预处理一下

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<set>
#include <vector>
#include<algorithm>
typedef unsigned long long ll;
using namespace std;
const ll HASH_CONSTAN=131;
ll p[100005]={1},hash_code[100005];
int main(){
    ios::sync_with_stdio(false);
    for(int i=1;i<=100005;i++)
        p[i]=p[i-1]*HASH_CONSTAN;
    string s;
    cin>>s;
    for(int i=0;i<s.size();i++)
        hash_code[i+1]=hash_code[i]*HASH_CONSTAN+s[i];
    int n;
    cin>>n;
    int l1,r1,l2,r2;
    while(n--){
        cin>>l1>>r1>>l2>>r2;
        (hash_code[r1]-hash_code[l1-1]*p[r1-l1+1])==(hash_code[r2]-hash_code[l2-1]*p[r2-l2+1])?cout<<"Yes"<<endl:cout<<"No"<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
字符串哈希算法是一种将字符串映射为数字的算法,常用于字符串的比较和匹配。在C++中,可以使用字符串哈希算法来加速字符串的比较操作。 引用\[1\]中的代码示例展示了一个使用字符串哈希算法的C++代码。该代码使用了前缀和数组和字符串数组来存储字符串,并通过计算哈希值来比较两个子串是否相等。其中,哈希值的计算使用了前缀和数组和幂运算。 引用\[2\]中的解释指出,使用字符串哈希的目的是为了比较字符串时不直接比较字符串本身,而是比较它们对应映射的数字。这样可以将子串的哈希值的时间复杂度降低到O(1),从而节省时间。 引用\[3\]中的代码示例也展示了一个使用字符串哈希算法的C++代码。该代码使用了前缀和数组和字符串数组来存储字符串,并通过计算哈希值来比较两个子串是否相等。与引用\[1\]中的代码类似,哈希值的计算也使用了前缀和数组和幂运算。 综上所述,字符串哈希算法是一种将字符串映射为数字的算法,常用于字符串的比较和匹配。在C++中,可以使用前缀和数组和幂运算来计算字符串哈希值,并通过比较哈希值来判断两个子串是否相等。 #### 引用[.reference_title] - *1* [C++算法题 # 33 字符串哈希](https://blog.csdn.net/weixin_44536804/article/details/123425533)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [字符串哈希(c++)](https://blog.csdn.net/qq_41829492/article/details/120980055)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [AcWing 841. 字符串哈希(C++算法)](https://blog.csdn.net/YSA__/article/details/108453403)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值