【问题标题】: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] 表示bi-th 元素和|b|-|a|+i-th 元素之间的个数,A[|b|-|a|-1] - A[i-1] 相同)。这些元素应与ai-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
      

      【讨论】:

        猜你喜欢
        • 2017-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多