【问题标题】:Finding all subtree repeats in a rooted, labeled, directed tree在有根、有标签、有向树中查找所有子树重复
【发布时间】:2016-05-11 03:21:24
【问题描述】:

对于我目前正在进行的一个研究项目,我需要做的任务之一如下:给定一个有根的、标记的、有向的树,我需要找到所有的子树重复 在这棵树内;换句话说,给定 all 树的子树(至少有一个节点),我需要将所有具有相同标签集的子树组合在一起 相同的层次结构结构体。例如,假设我们有以下树,其根为 A:

一种 / \ / \ 乙 |\ |\ C C B A | C

在这种情况下,有几个重复的子树模式,比如下面……

模式 1(出现 3 次):

一种 | 乙 | C

模式 2(出现 3 次):

一种 |\ 乙 | C

模式 3(出现 2 次):

一种 | 乙

...等等等等。仅供参考,我关注的“有根、有标签、有向树”是从 JavaScript 代码生成的抽象语法树 (AST)。

现在,我提出了自己的算法来查找所有子树重复。当 JavaScript 代码非常小时(因为 AST 也很小)时,它运行良好,并且算法立即完成。但是当我将 JavaScript 代码的行数增加到只有 10 行时,算法甚至在一个多小时后都没有完成执行! 所以我的问题是,有没有人知道一种更有效和可扩展的算法来查找所有子树重复?仅供参考,我实现该算法的语言也是 JavaScript。

供您参考,我当前的算法基本上是一种递归算法,它对树进行后序遍历(在这种情况下,后序的意思是“先访问该节点的子节点,然后再访问该节点”) .在每次节点访问时,算法通过遍历算法中早先确定的其子节点的子树的每个组合,找到以该节点为根的所有子树;对于它找到的每个以该节点为根的子树,该算法基于三件事计算一个哈希值:(1)节点的标签; (2) 出现在该子树的节点的子节点数; (3) 当前出现在此子树中的子子树的哈希值。然后将散列到相同值的子树放置在同一组中。 (散列函数的潜在不准确性也需要解决,但我什至还没有到达那部分......)。

【问题讨论】:

    标签: javascript algorithm performance tree abstract-syntax-tree


    【解决方案1】:

    您正在尝试在抽象语法树中重新发明克隆检测。是的,匹配树的基本思想是使用散列将它们放入“可能等效”的桶中,然后检查那些可能等效的实际等效。这是一个经典的编译器算法,用于支持查找公共子表达式。

    如果等效子树的数量与散列桶的数量相比较小,并且您的散列算法不错,那么这在树的大小上基本上是线性的。 (糟糕的散列或一个桶可以使它成为 N^2)。

    我不太了解你的算法;听起来你基本上是这样做的。如果没有更精确的特征(例如伪代码),就很难看出哪里出了问题。

    研究很久了。请参阅我关于 CloneDR 的技术论文,这是一个执行此操作的工具:http://www.semanticdesigns.com/Company/Publications/ICSM98.pdf(您可以在同一站点找到 JavaScript CloneDR)。

    要找到几乎相同的子树是一个更困难的问题,论文也提到了这一点。这是迄今为止最有趣的部分, 而且更难快速完成。

    我们定期在数百万条线路系统上运行 CloneDR。在这种规模下,完成其并行、编译为本机代码的实现确实需要数小时。 JavaScript 可能不是你的朋友。

    【讨论】:

    • 我认为他的算法在树的大小上比线性的要差得多,因为他不仅考虑了以每个节点为根的“完整”子树,还考虑了“部分”子树——也就是说,子树不需要包含其根的所有后代。 Perl 单行代码告诉我,在高度为 9 的完全二叉树中有 2441406 个这样的子树,而高度为 10 的完全二叉树中有 12207031 个。
    • 顺便说一句,我认为您似乎描述的问题(其中只考虑“完整”子树)可能是 OP 想要实际做的......
    • 如果您尝试匹配所有可能的“部分”子树,您会遇到类似于 CloneDR 在查找“几乎未命中”时解决的问题,即共享子结构的多个树。 CloneDR 对与树的质量相比差异较小的树感兴趣;这在实践中意味着更小的部分子树集。但正如您所指出的,它避免枚举所有可能的部分子树,因为这样做的成本很高。
    • @IraBaxter 感谢您的快速回复!我实际上已经阅读了您的 CloneDR 论文,事实上,这就是我对散列的想法的地方。我尝试通过电子邮件联系您和您的合著者,询问您是如何在 AST 中找到所有子树的,但我认为电子邮件地址可能在论文不久前发表后已经失效;所以我只是想出了自己的算法来查找子树,并将其与您将散列到“可能等效”存储桶的想法融合在一起。
    • @IraBaxter 只是为了给你一些背景信息,克隆检测不是我研究的主要目标,但它只是我作为整体的一部分纳入的东西设计。另外,是的,我最初是在寻找查找所有子树重复的方法,包括部分子树,因为这将为我正在处理的问题提供更高的准确性。但是,根据您所说,似乎缺乏可扩展性主要来自于寻找部分子树而不是完整子树,因此我可能不得不重构我的设计以简单地采用启发式并仅考虑完整子树。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-11
    相关资源
    最近更新 更多