一尘不染

在数字序列的末尾查找重复序列

algorithm

我的问题是:我的数字序列很大。我知道,在某个点之后,它变成周期性的-
也就是说,序列的开头有k个数字,然后在序列的其余部分又有m个重复的数字。例如,为了使这一点更加清楚,序列可能如下所示:[1、2、5、3、4、2、1、1、3、2、1、1、3、2、1、1、3
,…],其中k为5,m为4,则重复块为[2,1,1,3]。从该示例可以清楚地看出,我可以在较大的块中包含重复的位,因此仅查找重复的第一个实例无济于事。

但是,我不知道k或m是什么-我的目标是采用序列[a_1,a_2,…,a_n]作为输入并输出序列[a_1,…,a_k,[a_(k
+1),…,a_(k + m)]]-通过将大部分序列列为重复块来基本上截断更长的序列。

是否有解决此问题的有效方法?此外,可能更难但更理想的计算-
在生成有问题的序列时是否可以执行此操作,因此我必须生成最少的数量?我在该站点上看过其他类似的问题,但它们似乎都处理序列而没有开始的非重复位,并且通常不必担心内部重复。

如果有帮助/有用,我也可以弄清楚为什么我要看这个以及我将用它做什么。

谢谢!

编辑:首先,我应该提到,我不知道输入序列是否恰好在重复块的结尾处结束。

我正在尝试解决的现实问题是为二次无理数(实际上是负CFE)的连续分数展开(CFE)写一个漂亮的闭式表达式。为这些CFE生成部分商*达到任何精确度都是非常简单的-
但是,在某个点上,用于二次无理数的CFE的尾部成为重复块。我需要在此重复块中使用部分商。

我目前的想法是:也许我可以改编一些建议使用的算法,从正确的角度开始使用这些序列之一。另外,也许有一些证据可以证明为什么二次非理性是周期性的,这将帮助我了解为什么它们会重复出现,这将帮助我提出一些容易检查的标准。

*如果我将连续分数扩展写为[a_0,a_1,…],则将a_i称为部分商。

一些感兴趣的人可以在这里找到一些背景信息:http
:
//en.wikipedia.org/wiki/Periodic_continued_fraction


阅读 226

收藏
2020-07-28

共1个答案

一尘不染

您可以使用 滚动散列
来实现线性时间复杂度和O(1)空间复杂度(我认为是这种情况,因为我不相信您可以使用两个互不相同的倍数的无限重复序列) 。

算法:您只需保留两个滚动散列,它们的扩展如下:

                       _______  _______  _______
                      /       \/       \/       \
...2038975623895769874883301010883301010883301010
                      .        .        .      ||
                      .        .        .    [][]
                      .        .        .  [ ][ ]
                      .        .        .[  ][  ]
                      .        .       [.  ][   ]
                      .        .     [  . ][    ]
                      .        .   [    .][     ]
                      .        . [      ][      ]
                      .        [       ][       ]

在整个序列中继续这样做。第一遍将仅检测到重复2 * n次,重复一些n值。但这不是我们的目标:第一步,我们的目标是检测所有可能的时间段。当我们按照执行此过程的顺序进行操作时,我们还将跟踪所有需要稍后检查的相对黄金时段:

periods = Set(int)
periodsToFurthestReach = Map(int -> int)

for hash1,hash2 in expandedPairOfRollingHashes(sequence):
    L = hash.length
    if hash1==hash2:
        if L is not a multiple of any period:
            periods.add(L)
            periodsToFurthestReach[L] = 2*L
        else L is a multiple of some periods:
            for all periods P for which L is a multiple:
                periodsToFurthestReach[P] = 2*L

完成此过程后,我们将获得所有期间的列表以及到达的时间。我们的答案可能是范围最广的答案,但是我们检查所有其他时间段是否重复(很快,因为我们知道我们要检查的时间段)。如果这在计算上很困难,我们可以通过在遍历列表时删掉句点(不再重复)来进行优化,这非常类似于Eratosthenes的筛子,方法是将下一次希望重复的时间保留在优先队列中。

最后,我们仔细检查结果以确保没有哈希冲突(即使有,也不会出现黑名单并重复)。

在这里,我假设您的目标是使非重复长度最小化,并且不给出可以进一步考虑的重复元素;您可以修改此算法以查找所有其他压缩(如果存在)。

2020-07-28