我想到了一种可行的分而治之的方法。
首先,在预处理中,您需要将小于输入大小(n / 3)一半的所有数字插入列表中。
给定一个字符串:(0000010101000100
请注意,此特定示例有效)
将从1到(16/2)的所有素数(和1)插入列表中:{1,2,3,4,5,6,7}
然后将其分成两半:
100000101 01000100
继续执行此操作,直到获得大小为1的字符串为止。对于其中所有大小为1的所有字符串,将其索引添加到可能性列表中;否则,将其添加为1。否则,返回-1返回失败。
您还需要返回与每个起始索引关联的仍然可能的间距列表。(从上面创建的列表开始,然后删除数字)。这里,空列表意味着您只处理一个1,因此此时可以有任何间距;否则,列表包括必须排除的间距。
因此,继续上面的示例:
1000 0101 0100 0100
10 00 01 01 01 00 01 00
1 0 0 0 0 1 0 1 0 1 0 0 0 1 0 0
在第一个合并步骤中,我们现在有八套两套。首先,我们有可能设置一个集合,但是我们知道由于存在另一个零,所以不可能以1间隔。因此我们返回0(用于索引)和{2,3,4,5,7},因为不可能用1隔开。在第二个中,我们什么都没有,因此返回-1。在第三个中,我们有一个匹配,索引5中没有消除任何间距,因此返回5,{1,2,3,4,5,7}。在第四对中,我们返回7,{1,2,3,4,5,7}。在第五行中,返回9,{1,2,3,4,5,7}。在第六行,返回-1。在第七行中,返回13,{1,2,3,4,5,7}。第八,返回-1。
再次组合成四组,每组四个,我们有:
1000
:返回(0,{4,5,6,7})
0101
:返回(5,{2,3,4,5,6,7}),(7,{1,2,3,4,5,6 ,7})
0100
:返回(9,{3,4,5,6,7})
0100
:返回(13,{3,4,5,6,7})
分为八组:
10000101
:返回(0,{5,7}),(5,{2,3,4,5,6,7}),(7,{1,2,3,4,5,6,7})
01000100
:返回(9,{4,7}),(13,{3,4,5,6,7})
合并为一组十六个:
10000101 01000100
随着我们的进步,我们一直在检查到目前为止的所有可能性。到这一步为止,我们剩下的内容超出了字符串的末尾,但是现在我们可以检查所有可能性了。
基本上,我们以5和7的间隔检查第一个1,并发现它们未与1对齐。(请注意,每个检查都是恒定的,不是线性时间),然后我们检查第二个(索引5),其间隔为2、3、4、5、6和7,或者我们可以,但是我们可以在2处停止,因为实际上匹配。
!这是一个相当长的算法。
由于最后一步,我不知道它是否为O(n log n),但据我所知,到那里的一切肯定都是O(n log n)。稍后,我将再次讨论并尝试完善最后一步。
编辑:更改了我的答案以反映Welbog的评论。对不起,错误。当我有更多的时间来解密我再次写的内容时,我也会稍后编写一些伪代码。;-)