将文本增量组合成单个'超级串'的算法

时间:2011-06-27 19:16:53

标签: algorithm diff delta

我正在编写软件来跟踪作者对一本书的几个版本所做的更改。我已经编写了一些代码,它产生了一组描述两个版本之间差异的增量。

现在我正在寻找一种算法,将所有这些差异内联组合在一起,创建一个'超级字符串',其中包含在每个版本中插入和删除的所有文本。然后我想在HTML中标记字符串,其中包含有关添加和删除文本的位置的信息。

通过这种方式,我可以通过简单地将不同的CSS属性应用于文档来可视化文本之间的差异。

实施例

如果作者以这种方式更改了句子

-0-    --1--    ---2---    ---3---
' ' -> 'cat' -> 'crate' -> 'crane'

我的代码产生这些增量

0-1) <insert 'cat' at 0>
1-2) <insert 'r' at 1> <insert 'e' at 3>
2-3) <remove from 3 to 4> <insert 'n' at 3>

我想要处理以创建这样的文件:

<span class="inserted-1">c</span>
<span class="inserted-2">r</span>
<span class="inserted-1">a</span>
<span class="inserted-1 removed-3">t</span>
<span class="inserted-3">n</span>
<span class="inserted-2">e</span>

问题

完成此任务的最佳算法是什么?这个问题有名字吗?

1 个答案:

答案 0 :(得分:4)

您可以连接更改并跟踪插入/删除的时间。请注意,数字给出了字符串中的索引(并注意删除的字符不会增加索引)。

第1步: 0-1) <insert 'cat' at 0>

  • [0] c inserted at step 1
  • [1] a inserted at step 1
  • [2] t inserted at step 1

第2步: 1-2) <insert 'r' at 1> <insert 'e' at 3>

  • [0] c inserted at step 1
  • [1] r inserted at step 2&lt; =这是在此步骤中插入位置1
  • [2] a inserted at step 1
  • [3] t inserted at step 1
  • [4] e inserted at step 2&lt; =这是在此位置插入此位置3

请注意,由于另一次插入,'e'的位置实际上已移至4。

第3步: 2-3) <remove from 3> <insert 'n' at 3>&lt; =我将此更改为最小差异

  • [0] c inserted at step 1
  • [1] r inserted at step 2
  • [2] a inserted at step 1
  • [3] t inserted at step 1, removed at step 3&lt; =不再计数,因此下一个索引是相同的
  • [3] n inserted at step 3&lt; =这是在此位置插入此位置3
  • [4] e inserted at step 2

所以基本算法是:

  • 维护一个字符列表,以及插入步骤和删除步骤
  • 为每一步做
    • 将您的差异从此步骤分解为单个字符插入和删除
    • 在位置P处插入新的字符X执行以下操作:
      • 在列表中包含索引P的最新字符后插入新的字符X,将插入步骤设置为当前步骤并调整以下项目的索引(即添加一个)。
    • 在位置P do处删除
      • 通过将删除步骤设置为当前步骤并调整后面的索引(即减去一个索引),用索引P标记列表中的字符(仅存在其中一个仍存在,即未设置删除步骤) )

在这两种情况下都注意到此步骤中的先前插入/删除可能会改变当前操作的位置(一种方法可以轻松解决此问题,即从字符串末尾开始向后插入/删除)。

结果将是您在问题中指定的更改列表。对于大量的更改,它可能会变得非常难以理解,但它仍会描述文本的完整历史记录。