算法导论32.2 Exercises 答案

32.2-1

可见,\(p=26\bmod 11=4\)

按照算法RABIN-KARP-MATCHER的执行结果,可以计算出的\(t_s\)值如下标:

\(\begin{array}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}\hline s&0&1&2&3&4&5&6&7&8&9&10&11&12&13&14\\\hline t_s&9&3&8&4&4&4&4&10&9&2&3&1&9&2&5\\\hline \end{array}\)

可见一共有\(4\)次命中,但是仅有偏移\(6\)是有效偏移,因此其余的偏移\(3,4,5\)都是伪命中。

32.2-2

这题的思想比较简单:首先求出\(k\)个模式串的\(p\)\(p_1,p_2,\dots,p_k\),并且使用一个基于链接法的哈希表来存储这些\(p\)值和对应的字符串。只要哈希表的大小合适,那么只需要\(O(1)\cdot O(m(v+n/q))= O(m(v+n/q))\),其中\(v\)是有效偏移的数量。需要注意的是,只有\(p_1,p_2,\dots,p_k\)都是长度为\(m\)的情况下才能使用该算法RABIN-KARP-MATCHER'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
RABIN-KARP-MATCHER'(T, P, n, k, m, d, q)
h = d^(m - 1) mod q
let p[1 : k] be a new array by 0
let T be a new hash-table.
t0 = 0
for i = 1 to m
t0 = (d * t0 + T[i]) mod q
for j = 1 to k
p[j] = (d * p[j] + P[j, i]) mod q
for j = 1 to k
let x be a new node
x.key = p[j]
x.p = P[j]
// 节点x存的是字符串和它的哈希值。
CHAINED-HASH-INSERT(T, x)
//假设CHAINED-HASH-SEARCH'返回的是哈希表中和x.key相同的所有节点,而并非只是至多一个;hash是一个哈希函数。
for s = 0 to n - m
for v, pat in CHAINED-HASH-SEARCH'(T, hash(t_s))
if v == t_s
if pat[1 : m] == T[s + 1 : s + m]
print "Pattern " pat " occur with shifts" s
if s < n - m
t_{s + 1} = (d * (t_s - T[s + 1] * h) + T[s + m + 1]) mod q

对于模式串不等长的情况下,不能够使用上述哈希表的情况,只能分别独立地进行查询。通过数组模拟各种查询情况,最终整个过程由程序RABIN-KARP-MATCHER''给出,其时间复杂度为\(O(km(v+n/q))\),其中\(v\)是有效偏移的数量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
RABIN-KARP-MATCHER''(T, P, n, k, d, q)
h = d^(m - 1) mod q
let p[1 : k] be a new array by 0
let T be a new hash-table.
for j = 1 to k
t0 = 0
for i = 1 to |P[j]|
p[j] = (d * p[j] + P[j, i]) mod q
t0 = (d * t0 + T[i]) mod q
for s = 0 to n - |P[j]|
if p == t_s
if P[j, 1 : |P[j]|] == T[s + 1 : s + m]
print "Pattern " P[j] " occur with shifts" s
if s < n - m
t_{s + 1} = (d * (t_s - T[s + 1] * h) + T[s + m + 1]) mod q

32.2-3

这道题的本质思想是将二维的情况转化为一维。对于每相邻\(m\)行,我们先预处理出一个长度为\(n\)的数组\(U\),然后再在数组\(U\)上处理一维的情况,注意处理一行\(U\)的情况时,不像RABIN-KARP-MATCHER那样以\(d\)作为进制,而是以\(d'=d^m\)来作为进制。和RABIN-KARP-MATCHER同样的是,判断一个字符矩阵对应的值\(t\)是否和\(p\)相同只需要\(O(1)\)的时间即可完成。

一共需要判断\((n-m+1)^2\)种情况,因此在最坏情况下,这个二维版本的算法将会达到\(O((n-m)+1^2 \cdot m^2)=O(n^4)\)。具体过程由RABIN-KARP-MATCHER-2D给出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
RABIN-KARP-MATCHER-2D(T, P, n, m, d, q)
ha = d ^ (m * (m-1)) mod q
hr = d ^ (m-1) mod q
d' = d ^ m mod q
p = 0
for j = 1 to m
for i = 1 to m
p = (d * p + P[i, j]) mod q
let U[1 : n] be a new array by 0
for j = 1 to n
for i = 1 to m
U[j] = (d * U[j] + T[i, j]) mod q
for rs = 0 to n - m
u0 = 0
for j = 1 to m
u0 = (d' * u0 + U[j]) mod q
for cs = 0 to n - m
if p == ts
if P[1 : m,1 : m] == T[rs + 1:rs + m,cs + 1:cs + m]
print "Pattern occurs with shift" (rs, cs)
if cs < n - m
u_{cs + 1} = (d' * (u_{cs} - U[cs + 1] * ha) + U[cs + m + 1]) mod q
if rs < n - m
for j = 1 to n
U[j] = (d * (u[j] - T[rs + 1, j] * ha) + T[rs + m + 1, j]) mod q

32.2-4

考虑令\(\displaystyle{f(A,B,x)=\left(\sum_{i=0}^{n-1}(a_i-b_i)x^i\right)\bmod q}\)

如果两个文件相同,那么也就是说\(\forall i\in[0,n),a_i=b_i\)均成立,那么此时任取\(x\in[0,q)\),都必定有\(A(x)=B(x)\)

否则,非零多项式\(f(A,B,x)\)的次数至多为\(n\)。由于\(q\)是一个质数,依照题目31.4-4的结论,方程\(f(A,B,x)=0\)最多有\(n\)个不同的根。由于\(x\)是从\([0,q)\)中选择的,因此任取\(x\in [0,q),f(A,B,x)=0\)的概率至多为\(\dfrac{n}{q}\)。由于\(q>10^3\cdot n\),因此\(f(A,B,x)=0\)的概率不会超过\(10^{-3}\),原结论成立。