文档详情

2.2字符串中的哈希.pdf

发布:2025-03-18约2.83千字共13页下载文档
文本预览下载声明

字符串中的哈希

主讲人:邓哲也

字符串中的哈希

假设有n个长度为L的字符串,问其中最多有几个字符串

是相等的。

直接比较两个长度为L的字符串是否相等时间复杂度是

O(L)的。

22

因此需要枚举O(n)对字符串进行比较,时间复杂度O(nL)

如果我们把每个字符串都用一个哈希函数映射成一个整数。

问题就变成了查找一个序列的众数。

时间复杂度变为了O(nL)

字符串中的哈希

一个设计良好的字符串哈希函数可以让我们先用O(L)的时

间复杂度预处理,之后每次获取这个字符串的一个子串的哈

希值都只要O(1)的时间。

这里我们就重点介绍BKDRHash

BKDRHash

BKDRHash的基本思想就是把一个字符串当做一个k进制数

来处理。

intk=19,M=1e9+7;

intBKDRHash(char*str){

intans=0;

for(inti=0;str[i];i++)

ans=(1LL*ans*k+str[i])%M;

returnans;

}

BKDRHash

假设字符串s的下标从1开始,长度为n。

ha[0]=0;

for(inti=1;i=n;i++)

ha[i]=(ha[i-1]*k+str[i])%M;

我们知道ha[i]就是s[1..i]的BKDRHash

那么现在询问s[x..y]的BKDRHash,你能快速求解吗?

BKDRHash

注意到ha[y]=s[1]ky-1+s[2]ky-2+…+s[x-1]ky-x+1+

s[x]ky-x+…+s[y]

注意到ha[x-1]=s[1]kx-2+s[2]kx-3+…+s[x-1]

而我们要求的s[x..y]的哈希值为s[x]ky-x+…+s[y]

可以发现s[x..y]=ha[y]-ha[x-1]ky-x+1

因此我们预处理出ha数组和k的幂次,每次询问s[x..y]

的哈希值,只要O(1)的时间。

边学边练

阿轩在纸上写了两个字符串,分别记为A和B。利用在数据结构与算法课

上学到的知识,他很容易地求出了“字符串A从任意位置开始的后缀子串”

与“字符串B”匹配的长度。

不过阿轩是一个勤学好问的同学,他向你提出了Q个问题:在每个问题中,

他给定你一个整数x,请你告诉他有多少个位置,满足“字符串A从该位

置开始的后缀子串”与B匹配的长度恰好为x。

例如:A=aabcde,B=ab,则A有aabcde、abcde、bcde、cde、de、e这6个

后缀子串,它们与B=ab的匹配长度分别是1、2、0、0、0、0。因此A有4

个位置与B的匹配长度恰好为0,有1个位置的匹配长度恰好为1,有1个位

置的匹配长度恰好为2。

1≤N,M,Q≤200000

边学边练

核心问题就是:给定两个字符串A,B。

求出A的每个后缀子串和B的最长公共前缀。

标准做法是扩展KMP,时间复杂度线性。

我们来用Hash试试看。

边学边练

前面已经提到,我们可以用O(n)预处理O(1)处理出一个子

串的哈希值。

求字符串A[i..n]与字符串B[1..m]的最长公共前缀?

二分!

二分长度mid

计算出A[i..i+mid-1]和B[1..mid]的哈希值,比较是否

相等。

因此时间复杂度是O(logn)的!

边学边练

llgetha(intx,inty){

returnha[y]-ha[x-1]*p[y-x+1];

显示全部
相似文档