Part2.1 字符串算法-哈希和哈希表

Part2.1 字符串算法-哈希和哈希表

字符串哈希算法

字符串的一般哈希函数为 f ( s ) = ∑ i = 1 ∣ s ∣ s i × b i   m o d   M f(s)=\sum_{i=1}^{|s|}s_i \times b^{i} \bmod M f(s)=i=1ssi×bimodM

显然上述函数的求解时 O ( n ) O(n) O(n) 的,并且实现效率低下

若要多次询问一个字符串 s s s 的子串哈希值,该算法显然无法满足要求,我们期望能够在 O ( 1 ) O(1) O(1) 时间算出 f ( s l . . . r ) = ∑ i = 0 r − l s i + l × b i   m o d   M f(s_{l...r})=\sum_{i=0}^{r-l}s_{i+l} \times b^{i} \bmod M f(sl...r)=i=0rlsi+l×bimodM 的具体数值

h ( s 0... i ) = ∑ j = 0 i s j × b j   m o d   M h(s_{0...i})=\sum_{j=0}^{i}s_j \times b^{j} \bmod M h(s0...i)=j=0isj×bjmodM

那么有:

h ( s 0... r ) = ∑ i = 0 r s i × b i   m o d   M h(s_{0...r})=\sum_{i=0}^{r}s_i \times b^{i} \bmod M h(s0...r)=i=0rsi×bimodM
h ( s 0... l − 1 ) = ∑ i = 0 l − 1 s i × b i   m o d   M h(s_{0...l -1})=\sum_{i=0}^{l -1}s_i \times b^{i} \bmod M h(s0...l1)=i=0l1si×bimodM
h ( s l . . . r ) = ∑ i = l r s i × b i   m o d   M = h ( s 1... r ) − h ( s 0... l − 1 ) = f ( s l . . . r ) × b l   m o d   M h(s_{l...r})=\sum_{i=l}^{r}s_i \times b^{i} \bmod M=h(s_{1...r})-h(s_{0...l -1})=f(s_{l...r}) \times b^{l} \bmod M h(sl...r)=i=lrsi×bimodM=h(s1...r)h(s0...l1)=f(sl...r)×blmodM

故我们可以依据前缀和 O ( 1 ) O(1) O(1) 算出 f ( s l . . . r ) f(s_{l...r}) f(sl...r)

但是由于计算中进行了模数运算,为了避免除法的出现,我们一般将函数 f f f 乘上 b N b^{N} bN,即 f ( s l . . . r ) = ∑ i = 0 r − l s i × b N + i   m o d   M f(s_{l...r})=\sum_{i=0}^{r-l}s_i \times b^{N+i} \bmod M f(sl...r)=i=0rlsi×bN+imodM

那么则有 f ( s l . . . r ) = ( h ( s 1... r ) − h ( s 1... l − 1 ) ) × b N − l f(s_{l...r})=(h(s_{1...r})-h(s_{1...l -1})) \times b^{N-l} f(sl...r)=(h(s1...r)h(s1...l1))×bNl

A. Oulipo

问题描述

给定字符串 A A A B B B,询问 B B B A A A 中出现了几次

解题思路

预处理 A A A B B B 的哈希值,由于 B B B 串长度固定,枚举起点, O ( 1 ) O(1) O(1) 判断 A [ i . . . i + ∣ B ∣ − 1 ] A[i...i+|B|-1] A[i...i+B1] B B B 的哈希值是否相等即可

时间复杂度 O ( n ) O(n) O(n)

D. Seek the Name, Seek the Fame

问题描述

给定若干字符串,在每个字符串中求出所有既是前缀又是后缀的子串长度

解题思路

枚举前缀长度,判断前后缀哈希值是否一致即可

时间复杂度 O ( n ) O(n) O(n)

E. Friends

问题描述

给定一个字符串 S S S,先将字符串 S S S 复制一次,得到字符串 T T T,然后在 T T T 中插入一个字符,得到字符串 U U U,给出字符串 U U U,重新构造出字符串 S S S

解题思路

显然 ∣ U ∣ |U| U 必须为奇数

设要添加字符的位置为 x x x,不妨设 x x x 在串 U U U 的前半段

f ( S ) = ∑ i = 0 ∣ U ∣ 2 − 1 U ∣ U ∣ 2 + i + 1 × b N + i   m o d   M f(S) = \sum_{i=0}^{\frac{|U|}{2}-1}U_{\frac{|U|}{2}+i+1} \times b^{N+i} \bmod M f(S)=i=02U1U2U+i+1×bN+imodM

f ( U 0... x − 1 ) = ∑ i = 0 x − 1 U i × b N + i   m o d   M f(U_{0...x-1})=\sum_{i=0}^{x-1}U_{i} \times b^{N+i} \bmod M f(U0...x1)=i=0x1Ui×bN+imodM

f ( U x + 1... ∣ U ∣ 2 ) = ∑ i = x + 1 ∣ U ∣ 2 U i × b N + i − x − 1   m o d   M f(U_{x+1...\frac{|U|}{2}})=\sum_{i=x+1}^{\frac{|U|}{2}}U_{i} \times b^{N+i-x-1} \bmod M f(Ux+1...2U)=i=x+12UUi×bN+ix1modM

易得 f ( U 0... x − 1 ) + f ( U x + 1... ∣ U ∣ 2 ) × b x + 1 = f ( S ) f(U_{0...x-1}) + f(U_{x+1...\frac{|U|}{2}}) \times b^{x+1} = f(S) f(U0...x1)+f(Ux+1...2U)×bx+1=f(S)

x x x U U U 后半段时亦然

故枚举 x x x O ( 1 ) O(1) O(1) 判断左右两边 H a s h Hash Hash 值是否相等即可

总时间复杂度 O ( ∣ T ∣ ) O(|T|) O(T)

F. A Horrible Poem

问题描述

给出一个由小写英文字母组成的字符串 S S S,再给出 q q q 个询问,要求回答 S S S 某个子串 S l . . . r S_{l...r} Sl...r 的最短循环节的长度

解题思路

S l . . . r S_{l...r} Sl...r 的最短循环节长度为 x x x,则其一定满足 f ( S l . . . r − x ) = f ( S l + x . . . r ) f(S_{l...r-x})=f(S_{l+x...r}) f(Sl...rx)=f(Sl+x...r)

那么显然有 x x x 为子串长度的某个因子( x × k = r − l + 1 x\times k =r - l + 1 x×k=rl+1

所以做法一为 n \sqrt{n} n 枚举 r − l + 1 r - l + 1 rl+1 的所有约数然后找到最小的 x x x,时间复杂度 q ∣ S ∣ q\sqrt{|S|} qS

但是此题卡此根号做法

由于 x × k = r − l + 1 x\times k =r - l + 1 x×k=rl+1

考虑将 k k k 进行质因子分解,即:

k = p 1 a 1 p 2 a 2 . . . p m a m k=p_{1}^{a_{1}}p_{2}^{a_{2}}...p_{m}^{a_{m}} k=p1a1p2a2...pmam,那么 p 1 p 2 . . . p m p_{1}p_{2}...p_{m} p1p2...pm 同样为 r − l + 1 r-l+1 rl+1 的质因子,并且 ( r − l + 1 )   /   ( p 1 . . . p 2 ) (r - l + 1)\ / \ (p_{1}...p_{2}) (rl+1) / (p1...p2) 一定也为循环节,故枚举 r − l + 1 r - l + 1 rl+1 的所有约数,找到最小的 x x x 即可

总时间复杂度 O ( q l o g 2 ∣ S ∣ ) O(qlog_{2}^{|S|}) O(qlog2S)

H. Antisymmetry

题目描述

对于一个 0 / 1 字符串,如果将这个字符串 0 和 1 取反后,再将整个串反过来和原串一样,就称作「反对称」字符串。比如 00001111 和 010101 就是反对称的,而 1001 就不是
现在给出一个长度为 n n n 的 0 / 1 字符串,求它有多少个子串是反对称的,注意这里相同的子串出现在不同的位置会被重复计算

解题思路

如果一个串满足上述条件,那么以其中心向两边扩展的所有子串均满足要求,故可用马拉车算法求解,若用 H a s h Hash Hash 算法,则枚举中心轴,二分找到满足条件的最长子串即可,总时间复杂度 O ( n l o g 2 n ) O(nlog_{2}^{n}) O(nlog2n),若用马拉车算法可将其优化至 O ( n ) O(n) O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值