以下是我如何查看示例帖子的所有权(注意,我根本忘记在文本中添加标签,所以这里的示例中不计算简单的标签更改,但可以轻松添加):
打额头:伙计,我用的是修订号而不是用户号。结果重做如下:
User 38193 owns 42% (922 / 2171) of the final post
User 2635 owns 28% (625 / 2171) of the final post
User 116 owns 24% (529 / 2171) of the final post
User 745 owns 3% (76 / 2171) of the final post
User 13005 owns 0% (11 / 2171) of the final post
User 18941 owns 0% (5 / 2171) of the final post
User 8562 owns 0% (3 / 2171) of the final post
53 ms
所以根据我的算法,用户 38193(@Paul Oyster)拥有 42% 的帖子,而帖子 2635(@Simucal)拥有 28%,用户 116( @Mark Harrison)拥有 24%,其余的可以忽略不计。
从修订版中,我们可以看到原作者 Paul 仍然拥有大部分问题,而 Simucal 和 Mark 获得了良好的 nr。2 和 3。这些对应于修订版 nr。1(原帖),天然橡胶。14,这是 Simucal 的一个大型编辑,看起来它很好地显示了我的算法中的缺陷(见下文),并且 nr. 5 Mark 添加了 bash 脚本的地方。
那么我是如何得出这个答案的呢?好吧,该算法有一个缺陷,但我会回到它,但它是这样的:
基本上,原始帖子中的每个字节都被分配了编写它的用户的用户 ID。然后我使用一个可以处理乱序副本的 diff 算法,然后它会带来新作者复制的字节的用户 ID。新作者添加的任何内容都被分配了新作者的用户 ID。
例如,如果原作者写了两个句子,这些将被标记为他的用户 ID。然后另一位作者对其进行了修改,并在原两句之间添加了第三句。对于 diff 算法,这看起来像是新作者复制了第一句话,添加了新数据,然后复制了第二句话。因此,这些句子将正确地归因于它们的作者。
由于 diff 算法适用于字节,因此添加缺失标点符号或字母等微小的文本更改对所有权的影响可以忽略不计,并且几乎所有原始文本仍应归属于原作者。但是,在某些情况下,由于内部优化,即使只添加了一个字节,它也会使用“添加数据”操作。该算法及其实现最初是为处理文件差异而创建的,并在文件版本之间生成尽可能小的补丁,并且有时会优化小步骤,以便将其组合成兄弟操作,如果它会减小文件大小。
算法中的缺陷来自回滚。我注意到 Jeff 在评论中写道不会考虑回滚,但是如果用户编辑帖子而不是将其回滚,并且只是粘贴旧内容,实际上是撤销前作者的更改,那么所有文本归因于“回滚”的人,而不是提出信息的原作者。
此实现的源代码可在此处找到,适用于 Visual Studio 2008。请注意,该解决方案不执行任何操作,例如屏幕截图或其他任何操作,并且帖子内容被硬编码到 TestData 类中的源代码中,正确转义为引号等. 要替换文本,您需要更改该文件,或者实现一种从程序外部读取内容的方法。
无论如何,这里的算法更详细一点。
- 创建一个整数数组,只要原来的修改(其实我是通过UTF8编码成字节的,这就是我使用的长度)。用他现在拥有 100% 修订版的原作者的用户 ID 填充这个数组,每个字符/字节都是他的
- 将第一个修订版与下一个修订版进行比较。这种比较将产生一个操作列表。这些操作可用于获取原始修订版,对其应用操作,您将获得下一个修订版(更多内容见下文)。
- 假设原始帖子是您准备的用户 id 数组(当前仅包含一堆等于第一作者 id 的值),并将操作应用于此。这将产生一个新的 id 列表,其中一些是原作者,一些是第二作者。
- 保留第二个修订版和这个新的用户 id 列表,并在这个数据、下一个修订版和下一个修订版等之间运行步骤 2+3,直到你到达底部
此时,您有一个用户 ID 列表,它告诉您哪个用户添加了每个字符。
比较中的操作是以下两种操作之一:
比较结果是如何使用的,你取旧的内容(第一篇文章),并对其进行操作,然后生成下一个修订版。它基本上是一个差异。
当我将操作应用于我的用户 id 列表时,当我复制时,我只是复制,当我插入时,我总是插入一些 id 等于存储在操作中的长度。
让我举个例子吧:
原帖:
This is the first post
下一篇:
This is the next post, it is based on the first post.
因此,操作列表将是:
- 复制 12 个字符 'This is the '
- 插入“下一个”
- 复制 5 个字符的“帖子”
- 插入17个字符',它基于'
- 复制14个字符'第一篇文章'
- 插入 1 个字符 '.'
如果我改为使用用户 ID,我将首先拥有这个数组:
0000000000000000000000
This is the first post
现在我应用这些操作,并且对于每个插入,我插入一个 1 代替:
00000000000011110000011111111111111111000000000000001
This is the next post, it is based on the first post.
现在我只计算我有多少个 0 和 1:
- 0 的:31
- 1 个:22
用户 0 拥有 31/(31+22) 个帖子,用户 1 拥有 22/(31+22) 个帖子。
换算成百分比:用户 0 拥有 58%,用户 1 拥有 42%。
现在,这个算法的问题在于回滚,以及添加丢失/删除的内容。
例如,如果您有用户 A、B 和 C,并且用户 A 发布的内容确实让用户 B 不屑一顾,那么用户 B 会进入并删除所有内容,并仅添加“这就是垃圾”。当用户 C 看到这一点时,他编辑了帖子,并添加了 A 发布的所有内容,可能还有修复。用户 C 现在拥有 100% 的帖子。
我不知道如何解决上述问题。
如果有趣的话,我将在今晚晚些时候发布执行此操作的代码。
应用于“quick brown fox”示例,将用户重新编号为 1-3,我得到以下信息:
User 3 owns 75% (45 / 60) of the final post
User 1 owns 25% (15 / 60) of the final post
请注意,仅添加了“有时”部分(随后被删除)的用户 2 已从列表中删除。
帖子的ID如下:
The quick brown fox jumps over the lazy dog.
11111111111111111111111111111111111111111111 (44 = 100%)
The quick brown fox jumps, sometimes.
1111111111111111111111111222222222222 (25 / 12 ~ 68% / 32%)
I always see the speedy brown fox jumping over the lazy dog.
333333333333333333333331111111111111113333333333333333333333 (45 / 15 = 75% / 25%)
算法将处理的事情:
如果我在发布新帖子时复制了某些内容,即使我现在复制了我还添加的部分,算法也会正确地归因于复制的元素。例子:
This is the first post, which is cool
1111111111111111111111111111111111111
This is the second post, which is the second post.
11111111111122222211111111111111112222222222111111
^-- copied ------^
这个算法的唯一问题,以及这篇文章的全部内容是,我不完全确定它会产生我称之为直观公平的结果。可能是,我只是将程序组合在一起,但是可能需要对大量边缘情况进行更多测试,以确定它是否真的产生了人们会接受的东西。
另外,如果我只是从最初的帖子中转移东西,那么只有很小的部分,比如百分之几,将是我的。由于该算法本质上是一种差异算法,有时仅输出 1 或几个字节的复制操作的成本超过了仅将其原始插入的成本,因此有时它会将短字节序列视为已插入,尽管它们可能是从原始帖子中复制的。