1. 简介

在本教程中,我们将探讨树编辑距离(Tree Edit Distance,TED)及其计算方法。与字符串编辑距离类似,TED 是用于衡量两个树结构之间差异的指标,常用于程序分析、XML文档比较、生物信息学等领域。

树编辑距离的核心思想是:通过一系列最小代价的操作将一棵树转换为另一棵树。常见的操作包括:

  • 插入节点(Insert)
  • 删除节点(Delete)
  • 重命名节点(Relabel)

2. 树编辑距离(TED)定义

树编辑距离是将一棵树 $ T_1 $ 转换为另一棵树 $ T_2 $ 所需的最小操作代价总和。这些操作通常包括:

  • relabel(u, v):将节点 $ u $ 的标签改为 $ v $
  • delete(u):删除节点 $ u $
  • insert(u):插入节点 $ u $

每种操作可以设定不同的代价,最终 TED 是使 $ T_1 \rightarrow T_2 $ 的最小代价序列的总代价。

2.1 示例

考虑如下两棵树:

ted example

设定操作代价如下:

$$ \text{cost(relabel)} = 2,\quad \text{cost(delete)} = \text{cost(insert)} = 3 $$

最小代价操作序列为:

$$ \begin{aligned} \text{delete } & c, e, g \ \text{relabel } & f \rightarrow g, d \rightarrow f, b \rightarrow e, a \rightarrow x \ \end{aligned} $$

总代价为 17,因此:

$$ \text{TED}(T_1, T_2) = 17 $$

2.2 TED 的意义

TED 的值依赖于操作定义和代价设定。不同的代价模型会导致不同的 TED 值。因此,在具体应用中应根据业务场景合理定义操作和代价。

如果 TED 满足距离度量的四个公理(非负性、对称性、三角不等式、自反性),则它定义了一个树的度量空间,可用于树结构的数学分析。

3. 通用递归计算方法

我们可以用递归方式定义 TED:

$$ \text{TED}(T_1, T_2) = \begin{cases} 0, & T_1 = T_2 \ \min_{a \in \mathcal{A}(T_1)} \left{ \text{cost}(a) + \text{TED}(a(T_1), T_2) \right}, & \text{otherwise} \end{cases} $$

其中:

  • $\mathcal{A}(T)$ 表示可对树 $ T $ 执行的操作集合
  • $\text{cost}(a)$ 是操作 $ a $ 的代价

这个递归可能导致指数级复杂度,但在引入 记忆化(Memoization) 后可以优化。例如,将树结构哈希后缓存中间结果,避免重复计算。

4. 基于节点的 TED 算法

我们重点讨论一种基于节点操作的 TED 算法,操作包括:

  • delete(u):删除节点 $ u $,其子节点继承为父节点的子节点
  • relabel(u, v):将节点 $ u $ 的标签更改为 $ v $
  • insert(u, parent):插入节点 $ u $ 并指定其父节点

4.1 假设与说明

  • 节点具有左右顺序
  • 每个节点最多被插入、删除或重命名一次
  • 操作代价为常数:$ c_{del}, c_{ins}, c_{rel} $

插入节点 $ u $ 到 $ T_1 $ 等价于从 $ T_2 $ 中删除该节点,因此我们只需考虑删除和重命名操作。

4.2 使用森林计算 TED

该算法在中间步骤中处理森林(多个子树)。通过后序遍历编号节点,定义子森林 $ T[i..j] $ 为编号从 $ i $ 到 $ j $ 的节点组成的森林。

例如:

post order sub forest

这样可以使用 动态规划 方法将问题分解为子问题。

4.3 递推公式

设 $ F_1 = T_1[i..j] $,$ r_1 $ 是其最右根节点,$ R_1 $ 是其最右子树。同理定义 $ F_2 $。

TED 的递推公式如下:

$$ \text{TED}(F_1, F_2) = \min \begin{cases} \text{TED}(F_1 - r_1, F_2) + c_{del} \ \text{TED}(F_1, F_2 - r_2) + c_{ins} \ \text{TED}(F_1 - R_1, F_2 - R_2) + c_{rel} + \text{TED}(R_1 - r_1, R_2 - r_2) \end{cases} $$

4.4 算法实现(使用记忆化)

我们使用一个哈希表缓存每个子问题的计算结果,键为四元组 $ (i_1, j_1, i_2, j_2) $,表示当前处理的两个子森林。

algorithm TEDMemoized(T1, T2, n, m):
    // INPUT
    //    T1 = the tree to transform
    //    T2 = the tree to transform T1 into
    //    n = the number of nodes in T1
    //    m = the number of nodes in T2
    //    T1 and T2 have been preprocessed to determine the left boundaries ℓ(·) for all the nodes
    //    results = the storage for the results, initially empty
    // OUTPUT
    //    The tree edit distance between T1 and T2

    if results[T1, T2] is known:
        return results[T1, T2]

    if T1 is empty and T2 is empty:
        return 0
    if T1 is not empty and T2 is empty:
        r1 <- find the rightmost root of T1
        return cost_del + TED(T1 - r1, empty set)
    if T1 is empty and T2 is not empty:
        r2 <- find the rightmost root of T2
        return cost_ins + TED(empty set, T2 - r2)

    Determine r1, R1, r2, R2

    ted_del <- TED(T1 - r1, T2) + cost_del
    ted_ins <- TED(T1, T2 - r2) + cost_ins
    ted_rel <- TED(T1 - R1, T2 - R2) + cost_rel + TED(R1 - r1, R2 - r2)

    results[T1, T2] <- min{ted_del, ted_ins, ted_rel}
    return results[T1, T2]

4.5 算法复杂度

该算法基于 Zhang-Shasha 的方法,其时间复杂度为:

$$ O(d_1 d_2 n m) $$

其中:

  • $ d_1, d_2 $:树 $ T_1, T_2 $ 的 keyroot 深度
  • $ n, m $:两棵树的节点数

若树是平衡的,则复杂度为:

$$ O(n \log n \cdot m \log m) $$

若树退化为链表(类似链表),则复杂度为:

$$ O(n^2 m^2) $$

4.6 回溯操作序列

在计算 TED 时,我们可以记录每一步选择的操作(删除、插入、重命名),从而在最终结果计算完成后回溯出完整的操作序列。

5. 小结 ✅

要点 说明
TED 定义 最小代价将 $ T_1 $ 转换为 $ T_2 $
操作类型 delete、insert、relabel
复杂度 $ O(d_1 d_2 n m) $,使用记忆化优化
适用场景 XML 比较、程序分析、生物信息学等
注意事项 合理定义操作代价,注意节点顺序和唯一操作限制

树编辑距离是一个强大的结构相似度衡量工具,尤其适用于结构化数据的比较。虽然其计算复杂度较高,但通过合理的算法设计和优化(如记忆化、预处理)可以有效提升性能。


原始标题:Tree Edit Distance