如何聚合序列中的循环?

时间:2012-06-25 19:10:30

标签: c++ algorithm graph-algorithm

我有一个代表节点之间跳数的对矢量,当有周期时我想要折叠(如在一个周期中的跳跃之间的总时间中将其显示为一个)。因此,例如,路径A - > B - > C - > D - > B - > C - > D - > E遍历子路径B - > C - > D两次,所以在我的结构中我会有类似的东西:

(A,B,1)(B,C,3)(C,D,2)(D,B,4)(B,C,5)(C,D,8)(D,E,6)

我最好减少到:

(A,B,1)(B,C,3+5)(C,D,2+8)(D,E,6)

将D从D存储到B(环回边缘时间)以分别聚合并且能够显示B - > C - > D以浓缩的方式(聚合边缘时间和所有D - > B实例的聚合环回时间以及我们循环次数的计数)

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

我会选择后缀数组后缀树。 只需生成令牌(在这种情况下(从,到))并将其放在后缀数组或后缀树中。然后你可以得到对。 简单但不有效的方式:

生成令牌,生成此令牌流的所有后缀。排序他们。然后你在那个排序列表中的所有常见子序列彼此靠近(令牌流长度 - 令牌流后缀长度=位置) 例如,您可以使用quicksort进行排序,或者只是寻找后缀数组实现。后缀数组可以在 O(n) O(n)空间中构建。找到最大对/重复(这就是你想要的)可以在 O(n + k)中完成(其中n = tokennumber,k =列表中的循环)

也许this有帮助。然后你可以产生一个令牌流,如:ABCDBCDE

快速而肮脏的解决方案是here

答案 1 :(得分:1)

基本上你会浏览路径,并将每个边缘((A,B),1)存储在map中,并将所有已发现的节点存储在set

  • 每当遇到一个将其目标点作为已发现节点的边时,您就知道它是一个环回边缘。

  • 每当您遇到相同的边缘时,请在map

  • 中添加其值