【问题标题】:Find length of overlap in strings [closed]查找字符串中的重叠长度[关闭]
【发布时间】:2018-07-19 22:40:54
【问题描述】:

你知道任何现成的方法来获取长度和两个字符串的重叠吗?但是只有R,也许来自stringr?我一直在看这里,不幸的是没有成功。

str1 <- 'ABCDE'
str2 <- 'CDEFG'

str_overlap(str1, str2)
'CDE'

str_overlap_len(str1, str2)
3

其他例子:

str1 <- 'ATTAGACCTG'
str2 <- 'CCTGCCGGAA'

str_overlap(str1, str2)
'CCTG'

str_overlap_len(str1, str2)
4

///

str1 <- 'foobarandfoo'
str2 <- 'barand'

str_overlap(str1, str2)
'barand'

str_overlap_len(str1, str2)
6

/// 是两个解决方案,总是选择总是重叠

str1 <- 'EFGABCDE'
str2 <- 'ABCDECDE'

str_overlap(str1, str2)
'ABCDE'

str_overlap_len(str1, str2)
5

我想知道这个自制的小功能,比如this one

【问题讨论】:

  • 输入为 str1 &lt;- c("EFGABCDE", "ABCDECDE") 时的预期输出是什么?请提供更多示例以了解预期输出。
  • 您在寻找最长的公共子串吗?查看stackoverflow.co/search?q=%5Br%5D+longest+common+substring
  • 我不明白你自己做和避免动态编程的意思
  • 这是我的实现(改编自@gaurav-taneja,如果字符串 a 比 b 长,效率更高):str_overlap = function(a, b) { if(nchar(a) &gt; nchar(b)){ a0 = a; a = b; b = a0 }; for(n in seq(1, nchar(a))) { sb = unique(combn(strsplit(a, "")[[1]], n, FUN=paste, collapse="")); if(length(unlist(str_extract_all(b, sb))) == 0){ r = prior; return(r) }; prior = unlist(str_extract_all(b, sb)) }; prior }

标签: r string bioinformatics overlap dna-sequence


【解决方案1】:

希望这会有所帮助:

library(stringr)

larsub<-function(x) {
  a<-x[1]
  b<-x[2]
  # get all forward substrings of a
  for(n in seq(1,nchar(a)))
    {
    sb<-unique(combn(strsplit(a, "")[[1]],n, FUN=paste, collapse=""))
    if(length(unlist(str_extract_all(b,sb)))==0){ 
      r<-prior
      return(r)
      }
    prior<-unlist(str_extract_all(b,sb))
    }

}

c1<-larsub(c('ABCD','BCDE'))
c2<-larsub(c('ABDFD','BCDE'))
c3<-larsub(c('CDEWQ','DEQ'))
c4<-larsub(c('BNEOYJBELMGY','BELM'))
print(c1)
print(c2)
print(c3)
print(c4)

输出:

> print(c1) [1] "BCD" > print(c2) [1] "B" "D" > print(c3) [1] "DEQ" > print(c4) [1] "BELM" `

免责声明:逻辑是从这里的 lcs 答案中借用的:@Rick Scriven 发布的longest common substring in R finding non-contiguous matches between the two strings

【讨论】:

    【解决方案2】:

    在我看来,您 (OP) 并不是很关心代码的性能,而是对在没有现成函数的情况下解决它的潜在方法更感兴趣。所以这是我想出的一个例子来计算最长的公共子串。我必须注意,即使可能有几个相同的长度,这也只会返回找到的第一个最大的公共子字符串。这是您可以修改以满足您的需求的东西。请不要指望这会非常快 - 它不会。

    foo <- function(str1, str2, ignore.case = FALSE, verbose = FALSE) {
    
      if(ignore.case) {
        str1 <- tolower(str1)
        str2 <- tolower(str2)
      }
    
      if(nchar(str1) < nchar(str2)) {
        x <- str2
        str2 <- str1
        str1 <- x
      }
    
      x <- strsplit(str2, "")[[1L]]
      n <- length(x)
      s <- sequence(seq_len(n))
      s <- split(s, cumsum(s == 1L))
      s <- rep(list(s), n)
    
      for(i in seq_along(s)) {
        s[[i]] <- lapply(s[[i]], function(x) {
          x <- x + (i-1L)
          x[x <= n]
        })
        s[[i]] <- unique(s[[i]])
      }
    
      s <- unlist(s, recursive = FALSE)
      s <- unique(s[order(-lengths(s))])
    
      i <- 1L
      len_s <- length(s)
      while(i < len_s) {
        lcs <- paste(x[s[[i]]], collapse = "")
        if(verbose) cat("now checking:", lcs, "\n")
        check <- grepl(lcs, str1, fixed = TRUE)
        if(check) {
          cat("the (first) longest common substring is:", lcs, "of length", nchar(lcs), "\n")
          break
        } else {
          i <- i + 1L 
        }
      }
    }
    
    str1 <- 'ABCDE'
    str2 <- 'CDEFG'
    foo(str1, str2)
    # the (first) longest common substring is: CDE of length 3 
    
    str1 <- 'ATTAGACCTG'
    str2 <- 'CCTGCCGGAA'
    foo(str1, str2)
    # the (first) longest common substring is: CCTG of length 4
    
    str1 <- 'foobarandfoo'
    str2 <- 'barand'
    foo(str1, str2)
    # the (first) longest common substring is: barand of length 6 
    
    str1 <- 'EFGABCDE'
    str2 <- 'ABCDECDE'
    foo(str1, str2)
    # the (first) longest common substring is: ABCDE of length 5 
    
    
    set.seed(2018)
    str1 <- paste(sample(c(LETTERS, letters), 500, TRUE), collapse = "")
    str2 <- paste(sample(c(LETTERS, letters), 250, TRUE), collapse = "")
    
    foo(str1, str2, ignore.case = TRUE)
    # the (first) longest common substring is: oba of length 3 
    
    foo(str1, str2, ignore.case = FALSE)
    # the (first) longest common substring is: Vh of length 2 
    

    【讨论】:

    • 感谢您的努力。目前我正在尝试创建相同的功能,我会比较结果。当然,在这种特殊情况下,性能根本不重要。我只是尝试为自己的练习和培训解决一些信息学问题。干杯!
    猜你喜欢
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-22
    • 2017-06-13
    • 2013-05-03
    • 1970-01-01
    相关资源
    最近更新 更多