【问题标题】:Sum of all Hamming distances of a given string A from substrings of length |A| of another string B给定字符串 A 与长度为 |A| 的子串的所有汉明距离之和另一个字符串 B
【发布时间】:2020-01-12 15:37:13
【问题描述】:
给定两个二进制字符串 a 和 b,求 a 与长度为 |a| 的 b 的所有连续子串之间的汉明距离之和。
输入复制:
01
00111
输出复制:
3
解释:对于第一个示例情况,有四个长度为 |a| 的 b 的连续子字符串:“00”、“01”、“11”和“11”。 “01”和“00”之间的距离是|0 - 0| + |1 - 0| = 1.“01”和“01”的距离为|0 - 0| + |1 - 1| = 0。“01”和“11”之间的距离为|0 - 1| + |1 - 1| = 1. 最后距离计数两次,因为字符串“11”出现了两次。这些编辑距离之和为1 + 0 + 1 + 1 = 3。
在这个问题中,我只是想一个时间复杂度为 O(|a|.|b|) 的蛮力解决方案,比如字符串匹配算法......有没有更快的算法来解决这个问题
【问题讨论】:
标签:
string
algorithm
hamming-distance
【解决方案1】:
当您计算汉明距离的总和时,它可以非常快地完成:
H := sum of Hamming distances
compute array A and B such as the following:
A[i]: the number of zeros up to i-th element of b
B[i]: the number of ones up to i-th element of b
iterate over elements of a for i <- 0:|a|-1:
as a[i] should be compared with all elemetns of b[i] .. b[|b|-|a|+i]
its effect over the value of summing distances is:
if a[i] == 0:
H += B[|b|-|a|+i] - B[i-1]
else:
H += A[|b|-|a|-1] - A[i-1]
在上面的伪代码中,B[|b|-|a|+i] - B[i-1] 表示b 的i-th 元素和|b|-|a|+i-th 元素之间的个数,A[|b|-|a|-1] - A[i-1] 相同)。这些元素应与a 的i-th 成员进行比较,以计算汉明距离的总和。因此,该算法的时间复杂度为\Theta(|a| + |b|)。
【解决方案2】:
你可以在线性时间和恒定空间中做到这一点。
a 中的每个位将与b 中的|b| - |a| + 1 位进行比较,每个不匹配都会将所有汉明距离的总和加 1。
此外,对于a 的每个位,我们不需要知道将与b 进行比较的整个位序列。我们只需要知道它有多少个零和多少个。当我们在a 中向前移动一位时,相应的范围在b 中向前移动一位,我们可以很容易地在恒定时间内更新这些计数。
下面是python中的一个实现:
def HammingSum(a,b):
# compare initial range in b to first bit in a
range0 = len(b)-len(a)+1
numZeros = 0
numOnes = 0
for i in range(range0):
if b[i]=='0':
numZeros += 1
else:
numOnes += 1
total = numOnes if a[0]=='0' else numZeros
#adjust the range as we compare to the other bits
for i in range(len(b)-range0):
#count the bit we're adding to the end of the range
if b[range0+i]=='0':
numZeros += 1
else:
numOnes += 1
#uncount the bit we remove from the start of the range
if b[i]=='0':
numZeros -= 1
else:
numOnes -= 1
#compare range with bit in a
total += numOnes if a[i+1]=='0' else numZeros
return total