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

Arrays 在数字序列的末尾查找重复序列,arrays,algorithm,language-agnostic,sequence,repeat,Arrays,Algorithm,Language Agnostic,Sequence,Repeat,我的问题是:我有一个大的数字序列。我知道,在某一点之后,它会变成周期性的——也就是说,序列的开头有k个数字,然后序列的其余部分又有m个数字重复。作为一个更清楚的示例,序列可能如下所示:[1,2,5,3,4,2,1,1,3,2,1,1,1,3,…],其中k是5,m是4,重复块是[2,1,1,3]。从这个例子中可以清楚地看到,我可以在较大的块中有重复的位,所以仅仅寻找重复的第一个实例是没有帮助的 然而,我不知道k或m是什么——我的目标是将序列[a_1,a_2,…,a_n]作为输入,并输出序列[a_1

我的问题是:我有一个大的数字序列。我知道,在某一点之后,它会变成周期性的——也就是说,序列的开头有k个数字,然后序列的其余部分又有m个数字重复。作为一个更清楚的示例,序列可能如下所示:[1,2,5,3,4,2,1,1,3,2,1,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称为部分商

对于感兴趣的人,可以在此处找到一些背景信息:

从右侧搜索:

  • a_n==a_n-1吗
  • (a_n,a_n-1)==(a_n-2,a_n-3)
这显然是O(m^2)。唯一可用的界限似乎是m列出了几种好的循环检测算法,并给出了C中算法的实现。

您可以使用a实现线性时间复杂度和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
完成此过程后,我们会列出所有时段及其到达的距离。我们的答案可能是到达最远的时段,但我们会检查所有其他时段是否重复(快速,因为我们知道要检查的时段)。如果这在计算上有困难,我们可以通过删除时段(停止重复)进行优化当我们浏览这个列表时,非常像埃拉托什尼的筛子,通过保持一个优先级队列,当我们下一个期望周期重复时

最后,我们再次检查结果以确保没有散列冲突(即使存在,也不太可能有,黑名单和重复)


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

一旦序列重复多次,请考虑该序列。它将结束,例如……1234123411234123411234。如果您将重复部分如果字符串一直到最后一个重复周期之前,然后沿着该周期的长度滑动,您将发现序列末尾的子字符串与向左滑动的相同子字符串之间存在长匹配,与其长度相比,该距离很小

相反,如果你有一个字符串,其中a[x]=a[x+k]代表大量的x,那么你也有一个[x]=a[x+k]=a[x+2k]=a[x+3k]……因此当滑动一小段距离时与其长度相匹配的字符串必须包含重复

如果你看一下,你会发现你可以建立一个字符串所有后缀的列表,按排序顺序,按线性时间,还有一个数组,它告诉你每个后缀有多少个字符与前一个后缀有相同的排序顺序。如果你寻找这个值最大的条目,这将是我的字符串候选项…12341234112341234,两个后缀的起点之间的距离将告诉您序列重复的长度。(但在实践中,某种滚动哈希搜索可能更快更容易,尽管有相当可编码的线性时间后缀数组算法,如“简单线性工作后缀数组构造”卡卡宁和桑德斯)

假设在可用字符数为8、16、32、64、.2^n时应用此算法,最终找到一个re