Algorithm 有效地从一组列表中查找重叠段

Algorithm 有效地从一组列表中查找重叠段,algorithm,list,Algorithm,List,假设我有以下列表: [1,2,3,20,23,24,25,32,31,30,29] [1, 2, 3, 20, 23, 28, 29] [1, 2, 3, 20, 21, 22] [1, 2, 3, 14, 15, 16] [16, 17, 18] [16、17、18、19、20] 这里的秩序很重要。这些是加权图中深度优先搜索产生的节点。我想做的是将列表分解为唯一的路径(其中一个路径至少有2个元素)。因此,上述列表将返回以下内容: [1,2,3] [20, 23] [24, 25, 32, 31

假设我有以下列表:

[1,2,3,20,23,24,25,32,31,30,29]
[1, 2, 3, 20, 23, 28, 29]
[1, 2, 3, 20, 21, 22]
[1, 2, 3, 14, 15, 16]
[16, 17, 18]
[16、17、18、19、20]

这里的秩序很重要。这些是加权图中深度优先搜索产生的节点。我想做的是将列表分解为唯一的路径(其中一个路径至少有2个元素)。因此,上述列表将返回以下内容:

[1,2,3]
[20, 23]
[24, 25, 32, 31, 30, 29]
[28, 29]
[20, 21, 22]
[14, 15, 16]
[16, 17, 18]
[19,20]

我现在的总体想法是:

  • 查看所有列表对,在列表的开头创建一组重叠段的列表。例如,在上面的示例中,这将是输出:
    [1,2,3,20,23]
    [1, 2, 3, 20]
    [1, 2, 3]
    [16、17、18]

  • 下一个输出是:
    [1,2,3]
    [16、17、18]

  • 一旦我有了第2步中的列表,我会仔细查看每个输入列表,如果它与第2步中的一个列表匹配,就把前面的部分切掉。新列表如下所示:
    [20,23,24,25,32,31,30,29]
    [20, 23, 28, 29]
    [20, 21, 22]
    [14, 15, 16]
    [19,20]

  • 然后我返回并将步骤1应用于步骤3中被截断的列表。当步骤1没有输出任何重叠列表时,我就完成了

  • 第二步是这里比较棘手的部分。愚蠢的是,它实际上等同于解决原始问题,尽管在较小的列表中


    解决这个问题最有效的方法是什么?查看所有对显然需要O(N^2)时间,而步骤2似乎是浪费时间,因为我需要运行相同的过程来解决这些较小的列表。我正试图找出是否有更聪明的方法来实现这一点,但我被卡住了。

    解决方案似乎是修改Trie以达到这一目的。Trie压缩提供了一些线索,但是这里需要的压缩类型不会产生任何性能优势

    添加的第一个列表将成为它自己的节点(而不是k个节点)。如果存在任何重叠,节点将被分割,但决不会小于容纳数组中两个元素的大小

    图形结构的一个简单示例如下所示:

    insert (1,2,3,4,5)
    graph: (1,2,3,4,5)->None
    insert (1,2,3)
    graph: (1,2,3)->(4,5), (4,5)->None
    insert (3,2,3)
    graph: (1,2,3)->(4,5), (4,5)->None, (3,32)->None
    segments
    output: (1,2,3), (4,5), (3,32)
    
    子节点也应作为实际的Trie添加,至少在从数据结构添加/删除时有足够的子节点以避免线性搜索,并可能将运行时间增加N倍。如果实现了这一点,然后,数据结构具有与具有更高隐藏常数的Trie相同的大O性能。这意味着它需要O(L*N),其中L是列表的平均大小,N是列表的数量。获取分段在分段数量上是线性的

    最后的数据结构,基本上是一个有向图(例如,您的示例),如下所示,起始节点位于底部

    请注意,此数据结构可以在运行DFS时构建,而不是在后记中构建


    我最终解决了这个问题,对这个问题的思考略有不同。我考虑的不是节点序列(在每个连续的节点对之间隐含一条边),而是边序列。我基本上使用我最初发布的算法。步骤2是一个简单的迭代步骤,我反复识别前缀,直到没有更多的前缀可以识别。这非常快,处理边而不是节点确实简化了一切


    谢谢大家的帮助

    从本质上看,您希望将深度优先树分解为链。然而,奇怪的是,您将树表示为路径,并且不清楚您希望如何进行分解。另一方面,
    29
    如何出现在两个不同列表的末尾?DFS不会重新访问NodeSorry,但您尚未定义问题。所以没人能告诉你怎么解决它。您只给出了一个输出示例和一个潜在的、描述模糊的算法。如果您对输出内容给出准确的描述,那么您可能会得到有用的帮助。@NiklasB,我希望不深入讨论细节,但这是一个表示水网(管道、接头等)的图形。水实际上可以从两个方向流入同一节点。我在这里提供的路径是相同流的路径。以[1,2,3]为例。这意味着水从节点1流向节点2再流向节点3。节点3和节点4之间可能有联系,但如果水从4流到3(而不是从3流到4),那么它就不会被包括在内。@Gene,关于我如何定义这个问题,还有什么不清楚的?我需要从列表开始的唯一路径段(其中每个段至少有2个节点)。对于[1,2,3,4,5]、[1,2,3,5]、[1,2,3,5]、[1,2,5]的预期结果是什么?