在二进制字符串中查找最长子字符串,其中的子字符串不小于零

krl*_*mlr 2 language-agnostic algorithm

如何在二进制字符串中找到最长的子字符串,其中余额(即1和0的数量之差)> = 0?

例:

01110000010 - > 6:011100

1110000011110000111 - > 19:整个字符串

虽然这个问题看起来非常类似于最大值连续子序列(最大连续和)问题,但动态编程解决方案似乎并不明显.在分而治之的方法中,如何进行合并?毕竟是一种"高效"的算法吗?(一个简单的O(n ^ 2)算法将迭代所有可能起点的所有子串.)

这是查找子字符串的修改变体,带有一些附加条件.不同之处在于,在链接问题中,只允许这样的子串,其中余额永远不会低于零(在向前或向后方向上查看字符串).在给定的问题中,如果平衡在稍后阶段恢复,则允许平衡降至零以下.

Zru*_*uty 5

我有一个需要O(n)额外内存和O(n)时间的解决方案.

我们将索引的"高度"表示h(i)

h(i) = <number of 1s in the substring 1..i> - <number of 0s in the same substring>
Run Code Online (Sandbox Code Playgroud)

现在可以将问题重新表述为:发现ij诸如h(i) <= h(j)j-i -> max.

显然,h(0) = 0如果h(n) = 0,那么解决方案就是整个字符串.

现在让我们计算数组,B以便B[x] = min{i: h(i) = -x}.换句话说,让B[x]是最左边的索引ih(i)= -x.

该数组B[x]的长度最多n,并在一个线性通道中计算.

现在我们可以迭代原始字符串,并为每个索引i计算最长序列的长度,其中非负余额结束i如下:

Lmax(i) = i - B[MIN{0, h(i)}]
Run Code Online (Sandbox Code Playgroud)

Lmax(i)所有最大的i将给你所需的长度.

我把证明留作练习:)如果你想不通,请联系我.

此外,我的算法需要2次传递原始字符串,但您可以将它们合并为一个.