如何在二进制字符串的特定范围内找到010的数字

时间:2018-06-26 07:07:10

标签: string algorithm string-algorithm

给出一个二进制字符串。如何在字符串的特定范围内找到“ 010” 的出现。
例如,我有字符串“ 0100110” 。如果给定范围为 3 7 (基于1的索引),则输出将为 4 。我找不到解决它的更快方法。

尝试此操作时,我可以以 O(N)的复杂性来解决它。方法是-首先,我指出所有'1'在一定范围内的位置,然后使用这些位置,我找出后面两个'0'来回然后,将在后面找到的'0'的数量与单个'1'的数量乘以在后面找到的'0'的数量。然后将一定范围内每个'1'的相乘结果相加。

对于给定的示例,'1'在范围内的位置为 {5,6} 。现在,对于索引 5 ,我前后的数字分别为 2 1 。这样我们就可以将子序列“ 010” 设置为 2 。同样,对于索引 6 ,我们也得到的答案是 2 。我们总共可以将子序列“ 010” 总共进行 4 次。

但是当我们对给定的字符串有一定范围内的多个 Q 查询时,我的方法很容易达到时间复杂度 O(N 2 。我尝试了很多,但是没有找到优化方法。有人可以用小于 O(N 2 个复杂度的方法来帮助我吗?提及的时限应为 1秒。如果您提供伪代码,将是一个加号。

〜先谢谢了。

1 个答案:

答案 0 :(得分:4)

预处理:制作辅助数组,该数组包含到给定位置的累积零个数(aux [0] = 0)

  0 1 0 0 1 1 0  //string
0 1 1 2 3 3 3 4  //aux array A[]

对于给定的L..R范围扫描为1,对于1的每k个索引,获取范围内的零个数-O(1)操作

P[k] = (A[k] - A[L-1]) * (A[R] - A[k])
S = Sum(P[k], k=L..R)

因此,每个查询有O(R-L)个时间,Q个查询有最差情况O(Q*N)

但是要仔细看公式:

P[k] = (A[k] - A[L-1]) * (A[R] - A[k]) = 
       A[k] * (A[R] + A[L-1]) - A[k]^2 - A[R] * A[L-1] = 
       A[k] * LRSum - A[k]^2 - LRProd
S = Sum(A[k] for ones) * LRSum - Sum(A[k]^2) - LRProd * NumOfOnes 

请注意,LRSumLRProd是给定查询的常量,我们必须计算1位置的A [k]之和和相同位置的平方和。似乎我们可以使用相同的累积数组概念,并在每个查询中以O(1)的形式获取结果。

快速检查给出(3+3)*5 - (9+9) - 4*2 = 30-18-8 = 4作为您的示例。

使用累积数组:

  0 1 0 0 1  1  0  //string
0 1 1 2 3 3  3  4  //aux array A[]
0 0 1 1 1 4  7  7  //aux array B[]
0 0 1 1 1 10 19 19  //aux array C[]

Result = (B[R] - B[L-1]) * (A[R] + A[L-1]) - (C[R] - C[L-1]) - 
                 A[R] * A[L-1] * (R - L - 1 - (A[R] - A[L-1])) = 
         (7-1) * (4 + 1) - (19 - 1) - 4 * 1 * (7 - 2  - 4 + 1) = 4