实现最长公共子序列的并行算法

时间:2014-04-01 20:22:03

标签: algorithm parallel-processing lcs

我正在尝试实现http://www.iaeng.org/publication/WCE2010/WCE2010_pp499-504.pdf

中描述的最长公共子序列问题的并行算法

但是我在第4页的公式6中遇到了变量C的问题

eq(6)

该论文指的是第3页末尾的C on

  

C为Let C [1:l]为有限字母

我不确定这是什么意思,因为我猜它会将2个字符串ABCDEFABQXYEF设为ABCDEFQXY。但是如果我的2个蜇是一个对象列表(我的匹配测试的例子是obj1.Name = obj2.Name),我的C会在这里怎么办?只是两个阵列上的联合?

1 个答案:

答案 0 :(得分:5)

阅读并研究了论文之后,我可以说C应该是一个包含字符串字母表的数组,其中字母表大小(因此,C的大小)是l

然而,从你问题的外观来看,我觉得有必要对此进行更深入的研究,因为看起来你还没有全面了解。什么是 P[i,j],为什么需要它?答案是你不会真的需要它,但这是一个优雅的优化。在第3页,在 Theorem 1 之前,有人说:

  

[...]此过程在第k步时j-k = 0或a(i)=时结束   b(j-k)在第k步。假设该过程在第k个停止   步骤,k必须是使(i)= b(j-k)或j-k的最小数   = 0. [...]

(3)中的递归关系等价于(2),但根本区别在于(2)递归扩展,而(3)你从来没有递归调用,只要你知道k 。换句话说,(3)不递归扩展的魔力是你以某种方式知道(2)上的递归停止的位置,所以你立即查看那个单元格,而不是递归地接近它。

好的,但是你如何找到k的值?由于k是(2)达到基本情况的地方,因此可以看到k是你需要的列数"返回"在B上,直到您超出限制(即第一列填充0' s),您会在B中找到匹配项和A中的一个字符(对应于(2)中的基本情况)。请记住,您将匹配字符a(i-1),其中i是当前行。

所以,你真正想要的是在B j之前找到角色a(i-1)出现的最后位置。如果在B之前j中没有出现过这样的字符,那么这相当于在(2)中达到i = 0 or j-1 = 0的情况;否则,它与在(2)中到达a(i) = b(j-1)相同。

让我们看一个例子:

enter image description here

考虑该算法正在计算i = 2和j = 3的值(行和列以灰色突出显示)。想象一下,该算法正在处理以黑色突出显示的单元格,并应用(2)确定S[2,2](黑色位置左侧的位置)的值。通过应用(2),然后通过查看a(2)b(2)开始。 a(2)是C,b(2)是G,没有匹配(这与原始的,众所周知的算法相同)。该算法现在想要找到S[2,2]的值,因为需要计算S[2,3](我们所在的位置)。 S[2,2]尚不清楚,但文章显示可以在不引用i = 2行的情况下确定该值。在(2)中,选择第3种情况:S[2,2] = max(S[1, 2], S[2, 1])。请注意,如果您愿意,所有这个公式都在查看用于计算S[2,2]的位置。所以,换句话说:我们正在计算S[2,3],我们需要S[2,2],我们还不知道,所以我们要回到桌面上去看看S[2,2]的价值与我们在原始非并行算法中的表现方式非常相似。

什么时候停止?在此示例中,当我们在第二个C(当前列中的字母)之前的a(i)中找到TGTTCGACA字母(这是我们的T)时,它会停止当我们到达第0列时。由于C之前没有T,我们会到达第0列。另一个例子:

enter image description here

此处,(2)将以j-1 = 5停止,因为这是TGTTCGACA中显示C的最后一个位置。因此,递归在a(i) = b(j-1)时到达基本案例j-1 = 5

考虑到这一点,我们可以在这里看到一个快捷方式:如果您能够以某种方式知道k金额,j-1-k是(2)中的基本情况,那么您就不会必须通过分数表才能找到基本情况。

P[i,j]背后的整个想法。 P是一个垂直放置整个字母表的表格(左侧);字符串B再次水平放置在上侧。此表是作为预处理步骤的一部分计算的,它会准确地告诉您需要提前知道的内容:对于j中的每个位置B,它表示每个字符{{在C[i](字母表)中{1}} C中找到B的{​​{1}}之前的最后位置(注意j用于索引C[i],字母表,而不是字符串i。也许作者应该使用另一个索引变量来避免混淆)。

因此,您可以将条目C的语义视为以下内容: B中我在位置j 之前看到C [i]的最后一个位置。例如,如果您的字母为A,则P[i,j] P`为:

enter image description here

花点时间了解这张表。请注意sigma = {A, E, I, O, U}的行。请记住:对于B = "AOOIUEI", then中的每个位置,此行列出了最后已知的位置" O"。只有当O我们的值不是零时(它是2),因为它是B中第一个j = 3之后的位置。此条目表示O之前看到AOOIUEI的最后一个位置是位置2(事实上,BO,跟随B[2]之后的位置O }})。请注意,在同一行中,对于A,我们的值为3,因为现在j = 4的最后一个位置与O中的第二个O相对应。 (并且由于不再存在B,所以该行的其余部分将为3)。

回想一下,如果您希望轻松找到O的值,那么构建P是必需的预处理步骤,这会使得从等式(2)的递归停止。现在应该有意义k是您在(3)中寻找的P[i,j]。使用k,您可以在P时间内确定该值。

因此,(6)中的O(1)是字母表中的字母 - 我们正在考虑的字母。在上面的示例中,C[i]C = [A,E,I,O,U]C[1] = A等等。在等式(7)中,C[2] = Ec中{{1}的位置(正在考虑的字符串C的当前字母)存在。这是有道理的:毕竟,在构建得分表位置a(i)时,我们希望使用A来查找S[i,j]的值 - 我们想知道上次我们看到的位置在P之前k中的a(i)。我们通过阅读B来做到这一点。

好的,既然您已了解j的使用情况,那就让我们了解您的实施情况。

关于您的具体案例

在论文中,P[index_of(a(i)), j]显示为列出整个字母表的表格。迭代字母表是一个好主意,因为这种算法的典型用途是生物信息学,其中字母表比字符串P小得多,使字母表中的迭代更便宜。

由于您的字符串是对象序列,您的P将是所有可能对象的集合,因此您必须构建一个表A,所有可能的对象实例的集合(当然是废话)。这绝对是一个字母大小与字符串大小相比较大的情况。但请注意,您只会在与C中的字母对应的那些行中对P编制索引:PA中任何不在{P的行1}}没用,永远不会被使用。 这会让您的生活更轻松,因为这意味着您可以使用字符串C[i]构建A,而不是使用每个可能对象的字母表。

再次举例说明:如果您的字母为PAAEIOUAEEI,则您只会将{{1}编入索引在BAOOIUEI的行中,以便P中所需的全部内容:

enter image description here

这很有效,因为在(7)中,EI中字符P的条目,P[c,j]是{{1}的索引}}。换句话说:P始终属于c,因此为c的字符构建a(i)而不是使用整个字母表来完成C[c]的尺寸远小于A的尺寸。

现在你所要做的就是将相同的原则应用于你的任何物体。

我真的不知道如何更好地解释它。起初这可能有点密集。确保重新阅读它,直到你真正得到它 - 我的意思是每一个细节。在考虑实施之前,你必须掌握这一点。

注意:您说您正在寻找可信和/或官方来源。我只是另一名CS学生,所以我不是官方来源,但我认为我可以被认为是可信的"。我以前研究过这个,我知道这个主题。快乐的编码!