字符串哈希

文章介绍了字符串哈希的概念,通过计算字符串的哈希值以达到快速查询和比较的目的。在O(1)的时间复杂度下,可以初步判断字符串是否包含在另一个字符串中。通过预处理和滑动窗口方法,实现了一个寻找子串在主串中出现次数的程序,适用于处理大量文本数据。
摘要由CSDN通过智能技术生成

目录

1.定义:

2.字符串哈希值计算:

3.字符串哈希的使用:


1.定义:

        字符串哈希是将一段字符串换为一个数,当查询是否包含某个字符串时,可以每次O(1)复杂度进行比对。比如:abc对应1,acd对应2,sdf对应3。(具体数值由计算决定)

2.字符串哈希值计算:

        从第一个字符开始,逐次向后计算。计算公式:

hash[i] = hash[i-1] * base + (ull)(s[i - 1] - ‘A’ + 1);

 计算的本质就是b进制数的计算,b进制数位上的数字是字符对应的数字。

       

        从第i个字符到第j个字符的值的计算:

Hash(S')=Hash( j ) - H( i ) * b^(j-i)

3.字符串哈希的使用:

        先计算两个字符串的字符串哈希值,然后将短字符串的哈希值,分别和长字符串种等长的字符串哈希值对比,如果相同,则包含该字符串(重复概率很小,可以使用双哈希进行进一步验证)。

例子:

小 Z 同学没天都喜欢斤斤计较,今天他又跟字符串杠起来了。

他看到了两个字符串 s1 s2 ,他想知道 S1 在 S2 中出现了多少次。

现在给出两个串 S 1,S 2(只有大写字母),求 S 1 在 S 2 中出现了多少次。

数据范围字符串长度len, 1<len(s1)<len(s2)<10^6

字符取值 大写字母 和 小写字母

实现: 

这段代码实现了字符串哈希,并借此实现了字符串匹配搜索,即在一个字符串中找到另一个字符串出现的次数。

代码主要有以下几个部分:

1. 头文件和常量定义

#include <iostream>
#include <cstdio>
#include <string>

using namespace std;

typedef unsigned long long ull;

const int base = 131;

const int maxn = 1e6 + 5;


头文件中包含了输入输出流和字符串类库,const定义了两个常用到的变量,base是计算哈希值的权值,maxn是字符串最大长度。

2. 函数初始化

void init() {
    power[0] = 1;
    for (int i = 1; i <= 10002; i++)//预处理base^n
        power[i] = power[i - 1] * base;
}


该函数用于预处理出base的n次方,以便在计算哈希值的时候直接用power[n]来代替循环n次计算。

3. 主函数

int main() {

    init();

    scanf("%s", &sTemp1);
    scanf("%s", &sTemp2);

    s1 = sTemp1;
    s2 = sTemp2;

    //强烈建议这样读取字符串,节省时间

    int len1 = s1.size();
    int len2 = s2.size();

    for (int i = 1; i <= len1; ++i)
        hash1 = hash1 * base + (ull)(s1[i - 1] - 'A' + 1);

    hash2[0] = (s2[0] - 'A' + 1);

    for (int i = 1; i <= len2; ++i)
        hash2[i] = hash2[i - 1] * base + (ull)(s2[i - 1] - 'A' + 1);

    for (int i = 0; i <= len2 - len1; ++i) {
        ull hash = hash2[i + len1] - hash2[i] * power[len1];
        if (hash == hash1)
            ans++;
    }

    printf("%d\n", ans);

    return 0;
}


在主函数中,首先调用init函数进行初始化,然后输入两个字符串并存入s1和s2中,用size()函数获取两个字符串的长度。之后通过循环计算出s1和s2的哈希值,并且在s2中循环匹配s1的哈希值是否出现。最后输出匹配到的次数。

在哈希计算过程中,对于每个字符,先将其转为数字,再将数字作为加数乘以权值base,最后累加到哈希值中。因此针对每个位置,哈希值的计算公式为:

hash = hash * base + (ull)(s[i] - 'A' + 1);//这里-'A'+1的作用是将字符转化为数字

当要在字符串中匹配某个子串时,可以先计算子串的哈希值,再用滑动窗口的方法,在主串中循环计算哈希值进行匹配。

在这段代码中,由于字符串长度较长,为了避免函数调用带来额外的开销,使用scanf和预处理输入的方式进行字符串读取。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱码天天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值