【问题标题】:Lowest Common Ancestor Optimization最低共同祖先优化
【发布时间】:2013-10-01 15:22:49
【问题描述】:

我有一个基本数组,其中包含元素 [0 到 N - 1],其中每个元素都是一个结构,其索引 总是 指向数组中较早的位置.

有一次,作为更大算法的一部分,我想在节点 X 和之后的任何节点之间找到一个特定的 C 最低共同祖先。 p>

int LCA(a, b) {
    while (a != b) {
        if (a > b) {
            a = nodes[a].parent;
        } else {
            b = nodes[b].parent;
        }
    }
    return a;
}

for (y = x + 1; y < n; ++y) {
    if (LCA(x, y) == c) {
        //other code
    }
}

上面的代码是真正的伪代码。通过在使用时生成查找表,我设法稍微提高了 LCA() 的性能。像这样的:

int LCA(a, b) {
    if (lookup[a, b]) {
        return lookup[a, b];
    }
    oa = a; ob = b;
    while (a != b) {
        if (a > b) {
            a = nodes[a].parent;
        } else {
            b = nodes[b].parent;
        }
    }
    lookup[oa, ob] = a;
    lookup[ob, oa] = a;
    return a;
}

我知道有一种方法可以制作某种专门的 LCA() 函数,也就是说,以某种方式替换所有上述代码以对其进行专门化,这样它的速度就会大大提高。但是我没有想到任何有趣的事情。

我试图通过查看LCA(c, y) == LCA(x, y) 来查看是否可以简单地在CY 之间进行 LCA 检查,但这当然不准确。

重新计算:X 总是小于 YC 总是小于 X(因此 Y)。父母的指数总是比他们的孩子低(所以它是有序的)。

节点知道它们的深度会有帮助吗?

这段代码占了整个算法 80% 的 CPU 时间,总共需要大约 4 分钟。对此的解决方案将很容易从整体上改进算法。谢谢!

【问题讨论】:

  • 另外,老实说,我的直觉告诉我,这和你能得到的一样好——现在已经是亚线性时间了。我很惊讶查找表没有太大帮助,这似乎是记忆的主要候选者。可能会花费低于线性时间的一件事是在您将元素插入此数据结构时构建查找表,但这可能会占用O(n^2) 内存开销,使插入速度变慢,而且似乎不会微不足道。 (假设“查找表”是指“哈希表”。如果不这样做,我会使用一个。)
  • 记忆化不一定有帮助,这取决于你真正得到的查询。您应该使用更有效的 LCA 算法。可以通过一些预处理来回答 O(1) 中的查询。
  • 对预处理有什么建议吗?我没有使用哈希表 - 使用 2D 数组。
  • 您能解释一下您的查找表有何帮助吗?

标签: c++ c algorithm tree


【解决方案1】:

xyLCA 将是树的 euler tour (*) 中出现 x 和出现 y 之间高度最小的节点。要在O(1) 时间内找到这个问题,您需要使用this method 解决RMQ problem

(*):您的游览需要稍作修改才能正常工作。每次返回数组时(从对子的递归调用中返回),您也必须在数组中附加一个值。对于 wiki 树,它看起来像这样:

1 2 3 4 5 6 7 8 9 10 11
1 2 6 2 4 2 1 3 1 5  1

请注意,叶子出现两次是没有意义的(尽管它不会影响正确性)。

因此,例如,RMQ(2, 5) 将是这些节点中高度最小的节点:

2 3 4 5 6 7 8 9 10
2 6 2 4 2 1 3 1 5 

这是节点1

这不是您可以采用的唯一有效间隔。取最后一次出现的2 也是有效的:

6 7 8 9 10
2 1 3 1 5 

这也会以LCA 的形式返回1

这样,您可以在恒定时间内回答 LCA 查询,而线性时间花费在预处理上。

【讨论】:

    猜你喜欢
    • 2014-05-24
    • 1970-01-01
    • 1970-01-01
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多