我有一个关于在R中寻找最长公共子串的问题。在搜索StackOverflow上的一些帖子时,我了解了qualV包。然而,我看到这个包中的LCS函数实际上找到了string1中存在于string2中的所有字符,即使它们不连续。
为了解释,如果字符串是string1:“hello”string2:“hel12345lo”我期望输出为hel,但我得到的输出为hello。我一定是做错了什么。请看下面的代码。
library(qualV)
a= "hello"
b="hel123l5678o"
sapply(seq_along(a), function(i)
paste(LCS(substring(a[i], seq(1, nchar(a[i])), seq(1, nchar(a[i]))),
substring(b[i], seq(1, nchar(b[i])), seq(1, nchar(b[i]))))$LCS,
collapse = ""))
我也尝试了Rlibstree方法,但我仍然得到不连续的子字符串。此外,子字符串的长度也与我的预期不符。
> a = "hello"
> b = "h1e2l3l4o5"
> ll <- list(a,b)
> lapply(data.frame(do.call(rbind, ll), stringsAsFactors=FALSE), function(x) getLongestCommonSubstring(x))
$do.call.rbind..ll.
[1] "h" "e" "l" "o"
> nchar(lapply(data.frame(do.call(rbind, ll), stringsAsFactors=FALSE), function(x) getLongestCommonSubstring(x)))
do.call.rbind..ll.
21
7条答案
按热度按时间vuktfyat1#
这里有三种可能的解决方案。
base R中还有
adist()
和agrep()
,stringdist
包中有一些运行LCS方法的函数。下面我们来看看stringsidt
。它返回未配对的字符数。现在我已经对此进行了更多的探讨,我认为
adist()
可能是一条可行的道路。如果我们设置counts=TRUE
,我们得到一个匹配,插入等序列。所以如果你把它给stri_locate()
,我们就可以用这个矩阵来得到从a到B的匹配。因此,
M
值表示直接匹配。我们可以用stri_sub()
得到子串对不起,我没有解释得很好,因为我不太精通字符串距离算法。
gr8qqesn2#
利用@RichardScriven的洞察力
adist
could be used(它计算“近似字符串距离”。我做了一个功能更全面。请注意,"trafos"
代表用于确定两个字符串之间的“距离”的“转换”(底部的示例)编辑此答案可能会产生错误/意外结果;正如@wdkrnls所指出的:
我对“apple”和“big apple bagels”运行你的函数,它返回“appl”。我以为是“苹果”。
请参阅下面的错误结果解释。我们首先使用一个函数来获取列表中的
longest_string
:然后我们可以使用@RichardSriven的工作和
stringi
库:或者我们可以重写代码以避免使用任何外部库(仍然使用R的原生
adist
函数):以上两个函数都只将
'hello '
标识为最长的公共子串,而不是'hello r'
(无论哪个参数是两者中较长的):最后编辑*注意一些奇怪的行为 *,结果如下:
我期待
'hello'
,但由于转换实际上移动(通过删除)world中的“o”成为hello中的“o”-根据M
,只有 hell 部分被认为是匹配:使用this Levenstein tool可以观察到这种行为,它给出了两种可能的解决方案,相当于这两种转换
我不知道我们是否可以将
adist
配置为优先选择一种解决方案?(转换具有相同的“权重”-相同数量的“M”和“D”-不知道如何选择具有更大数量的连续M
的转换)最后,不要忘记adist允许传入
ignore.case = TRUE
(默认值为FALSE
)adist
的"trafos"
属性的密钥;从一个字符串到另一个字符串的“转换”:转换序列作为返回值的“trafos”属性返回,作为具有元素
M
、I
、D
和S
的字符串,指示匹配、插入、删除和替换iswrvxsc3#
我不知道你做了什么得到你的输出“你好”。基于下面的试错实验,
LCS
函数似乎将(a)如果一个字符跟在本来是LCS的字符后面,则不会将该字符串视为LCS;(B)找到多个等长的LCS(不像sub()只找到第一个LCS);(c)字符串中元素的顺序无关紧要--下面没有说明;以及(B)字符串在LCS调用中的顺序无关紧要--也没有显示。所以,a的“hello”在B中没有LCS,因为b的“hel”后面跟着一个字符。这是我目前的假设
上面A点:
上面B点:
tyky79it4#
deikduxw5#
使用biostrings:
返回:
所以我做了一个基准测试,虽然我的答案确实做了这件事,实际上给了你更多的信息,它比@Rich Scriven慢500倍。
ubbxdtey6#
我根据我的目的改编了@Rich Scriven的答案。目标是在向量中找到最长的公共字符串,而不是两个字符串之间的字符串。最后,可以在数据表中按组使用它。
示例:
rnmwe5a27#
LCSn函数(PTXQC包)可以找到输入向量中所有字符串的最长公共字符串。一个警告是,最短的字符串被用作基,因此在比较多个字符串时,它可能不会给予您想要的结果。但是,比较两个序列是一个很好的选择。