- 1、本文档共13页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
字符串中的哈希
主讲人:邓哲也
字符串中的哈希
假设有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];
文档评论(0)