我正在尝试实现http://www.iaeng.org/publication/WCE2010/WCE2010_pp499-504.pdf
中描述的最长公共子序列问题的并行算法但是我在第4页的公式6中遇到了变量C的问题
该论文指的是第3页末尾的C on
C为Let C [1:l]为有限字母
我不确定这是什么意思,因为我猜它会将2个字符串ABCDEF
和ABQXYEF
设为ABCDEFQXY
。但是如果我的2个蜇是一个对象列表(我的匹配测试的例子是obj1.Name = obj2.Name
),我的C会在这里怎么办?只是两个阵列上的联合?
答案 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)
相同。
让我们看一个例子:
考虑该算法正在计算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列。另一个例子:
此处,(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`为:
花点时间了解这张表。请注意sigma = {A, E, I, O, U}
的行。请记住:对于B = "AOOIUEI", then
中的每个位置,此行列出了最后已知的位置" O"。只有当O
我们的值不是零时(它是2),因为它是B
中第一个j = 3
之后的位置。此条目表示O
之前看到AOOIUEI
的最后一个位置是位置2(事实上,B
是O
,跟随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] = E
是c
中{{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
编制索引:P
中A
中任何不在{P
的行1}}没用,永远不会被使用。 这会让您的生活更轻松,因为这意味着您可以使用字符串C[i]
构建A
,而不是使用每个可能对象的字母表。
再次举例说明:如果您的字母为P
,A
为AEIOU
且A
为EEI
,则您只会将{{1}编入索引在B
和AOOIUEI
的行中,以便P
中所需的全部内容:
这很有效,因为在(7)中,E
是I
中字符P
的条目,P[c,j]
是{{1}的索引}}。换句话说:P
始终属于c
,因此为c
的字符构建a(i)
而不是使用整个字母表来完成C[c]
的尺寸远小于A
的尺寸。
现在你所要做的就是将相同的原则应用于你的任何物体。
我真的不知道如何更好地解释它。起初这可能有点密集。确保重新阅读它,直到你真正得到它 - 我的意思是每一个细节。在考虑实施之前,你必须掌握这一点。
注意:您说您正在寻找可信和/或官方来源。我只是另一名CS学生,所以我不是官方来源,但我认为我可以被认为是可信的"。我以前研究过这个,我知道这个主题。快乐的编码!