首页 > 其他分享 >字符串哈希

字符串哈希

时间:2023-04-14 21:00:41浏览次数:35  
标签:映射 get int long 哈希 字符串

算法简介

字符串哈希是将字符串映射为数字的算法,它通常用来解决快速判断两个字符串是否相等的问题。

时间复杂度

\(O(n + m)\)

实现原理

1. 构造原理

字符串哈希运用了进制的思想,将字符串变为 p 进制的数字。

如:""

可以映射为:\((X_1 * P^{n-1} + X_2 * P^{n-2} + \cdots + X^{n-1} + X_n * P^{0}) \mod Q\)

该过程中需要注意的点是:

  1. 字符不能映射为 0 ,否则会出现 A,AA,AAA 字符串全部映射为 0 的情况。
  2. P 一般取值 131 或 13331 时冲突概率最小。
  3. Q 一般取值 \(2^{64}\),等同于 unsigned long long 的数据范围,可以利用 C++ 的溢出机制自动取模。

2. 区间哈希值

这里用数组 h[i] 表示当前字符串前 i 个字符组成的字符串的哈希值

例如:"ABCDEFGHIJK"
h[1] = "A" 的哈希值
h[2] = "AB" 的哈希值
h[3] = "ABC" 的哈希值
...
h[11] = "ABCDEFGHIJK" 的哈希值

那么如何求得 [l,r] 区间内的哈希值呢?

给出公式:\(h[l,r] = h[r] - h[l-1] * p^{r-l+1}\)

假设有字符串 ABCD:

则有:

\(h[1] = A * p^0\)
\(h[2] = A * p^1 + B * p^0\)
\(h[3] = A * p^2 + B * p^1 + C * p^0\)
\(h[4] = A * p^3 + B * p^2 + C * p^1 + D * p^0\)

若要求 BC 的哈希值,那么根据公式则有:

\(h[2,3] = h[3] - h[1] * p^2\)

则有

\(h[3] - h[1] * p^2 = (A * p^2 + B * p^1 + C * p^0) - (A * p^0) * p^2 = B * p^1 + C * p^0 = "BC"\)

或者可以通俗理解,copy 一个大佬的解释:

算法实例

1. 题目描述

https://www.acwing.com/problem/content/description/843/

2. AC代码

#include <bits/stdc++.h>

typedef unsigned long long ULL;

const int N = 100010, P = 131; // P = 13331

int n,m;
char str[N];
ULL h[N], p[N];

ULL get(int l,int r)
{
    return h[r] - h[l - 1] * p[r - l + 1];
}

int main()
{
    std::cin >> n >> m;
    std::cin >> str + 1;
    
    p[0] = 1;
    for (int i = 1 ; i <= n ; i ++ )
    {
        h[i] = h[i - 1] * P + str[i];
        p[i] = p[i - 1] * P;
    }
    
    while(m -- )
    {
        int l1,r1,l2,r2;
        std::cin >> l1 >> r1 >> l2 >> r2;
        
        if(get(l1,r1) == get(l2,r2)) puts("Yes");
        else puts("No");
    }
    
    return 0;
}

参考

https://www.acwing.com/solution/content/24738/

标签:映射,get,int,long,哈希,字符串
From: https://www.cnblogs.com/NachoNeko/p/17317426.html

相关文章

  • 97. 交错字符串
    classSolution{public:boolf[110][110];boolisInterleave(strings1,strings2,strings3){intn=s1.size(),m=s2.size();if(n+m!=s3.size())returnfalse;s1=''+s1;s2=''+s2;s3=�......
  • python 正则处理字符串,使用函数
    """在正则截取的字符子串基础上,处理字符串Python的re模块提供了re.sub用于替换字符串中的匹配项。语法:re.sub(pattern,repl,string,count=0,flags=0)参数:pattern:正则中的模式字符串。repl:替换的字符串,也可为一个函数。string:要被查找替换的原始字符串。cou......
  • 对比Python中的列表、元组、字典、集合、字符串等之间异同
    1.数据类型列表、元组、字典、集合、字符串均属于python3的标准数据类型。字符串和元组属于不可变数据,即创建后不可修改。列表、字典、集合属于可变数据,即创建后可以修改元素。2.创建有元素的对象3.创建没有元素的对象列表使用eval()或list()或中括号[]进行创建,元素之间使用逗号分......
  • JavaScript 之 JSON [4] parse()和stringify() -JSON字符串和JavaScript对象数据之间
    JavaScript之JSON[4]parse()和stringify()-JSON字符串和JavaScript对象数据之间的相互转换1、JSON.parse()JSON.parse()方法用于将一个JSON字符串解析为一个JavaScript对象。JSON字符串必须使用双引号包括属性名和字符串值,不能使用单引号或无引号。语法:JSON.parse(text,r......
  • js 查找字符串中指定字符 模糊查询 不区分大小写
    varstr="helloworld!hellocoder!";//查找‘HELLO’是否存在,找不到返回nullvarreg=newRegExp('HELLO','i');varisHas=str.match(reg);console.log(isHas);//打印结果:["hello",index:0,input:"hellow......
  • 字符串匹配算法KMP
    KMP算法是字符串的匹配算法,比如我给一个名为《文本》的字符串,和一个名为《样板》的字符串,询问《样板》在《文本》中出现过的次数,这就需要字符串匹配算法。对于匹配,形象一点可以看例子:《文本1》="abcdefghigklmn"《样板1》="abc"=============================《文本2》="abcde......
  • Mysql_批量替换 MySQL 指定字段中的字符串
    批量替换的具体语法是:UPDATE表名SET 指定字段=replace(指定字段,'要替换的字符串','想要的字符串') WHERE条件;  如果你想把article表中ID小于5000的记录,content字段中“解决”替换成“解放”,那么语法就是:UPDATEarticleSET content=replace(content,'解决',......
  • 完善SQL二进制到IP地址字符串转换(Perfecting SQL binary to IP Address string conve
    我们使用二进制(16)字段来存储IP地址。我们这样做,因为它可以同时拥有IPv4和IPv6地址,并且很容易与.NetIPAddress类一起使用。但是,为了报告目的,我创建了以下SQL函数将二进制地址转换为IP地址字符串。CREATEFUNCTIONfn_ConvertBinaryIPAddressToString(@binaryIPbinary(......
  • 算法刷题-阶乘后的零(数学)、模拟计算器(算法初阶、基础知识)、解码方法(字符串、动态
    阶乘后的零(数学)给定一个整数n,返回n!结果中尾随零的数量。提示n!=n*(n-1)*(n-2)*...*3*2*1示例1:输入:n=3输出:0解释:3!=6,不含尾随0示例2:输入:n=5输出:1解释:5!=120,有一个尾随0示例3:输入:n=0输出:0提示:0<=n<=104**进阶:**你......
  • 哈希接近o1查找字符串
    P3538[POI2012]OKR-AHorriblePoem/*把这个人的因子分成循环节的因子:循环次数的因子:把循环次数的因子除去,也就是循环节的因子了循环节肯定是由某些因子组成的把因子从小到大除一次就可以了如果能够除掉这个因子,那除掉就一定是最有的*/#include<bits/stdc++.h>usi......