用R找到重复的子串

时间:2014-06-15 14:03:55

标签: r

我有以下代码来查找字符串中的模式(连续重复的子字符串),比如0110110110000。输出模式为011110,因为它们都在字符串中重复。可以对以下代码进行哪些更改?

我想识别从给定字符串中的任何位置开始的子串,并且至少重复阈值次数。在上面提到的字符串中,阈值是三(th = 3)。重复的字符串应该是最大重复字符串。在上面的字符串中,110011都满足这些条件。

我尝试这样做:

reps <- function(s, n) paste(rep(s, n), collapse = "") # repeat s n times

find.string <- function(string, th = 3, len = floor(nchar(string)/th)) {
for(k in len:1) {
    pat <- paste0("(.{", k, "})", reps("\\1", th-1))
    r <- regexpr(pat, string, perl = TRUE)
    if (attr(r, "capture.length") > 0) break
}
if (r > 0) substring(string, r, r + attr(r, "capture.length")-1) else ""
}

1 个答案:

答案 0 :(得分:3)

您可以使用regex

执行此操作
s <- '0110110110000'

thr <- 3

m <- gregexpr(sprintf('(?=(.+)(?:\\1){%s,})', thr-1), s, perl=TRUE)

unique(mapply(function(x, y) substr(s, x, x+y-1), 
              attr(m[[1]], 'capture.start'), 
              attr(m[[1]], 'capture.length')))

# [1] "011" "110" "0"

gregexpr中的模式使用正向前瞻来防止匹配消耗字符(因此允许重叠匹配,例如011110)。我们对捕获的组使用重复(至少thr - 1次)反向引用来查找重复的子字符串。

然后我们可以通过从gregexpr的结果的属性(即对象m)中获取起始位置和长度来提取匹配的子串。

您没有指定最小字符串长度,因此返回0作为重复的子字符串之一。如果考虑到最小和/或最大子字符串长度,则可以修改正则表达式的第一个子表达式。例如,以下内容仅匹配至少包含2个字符的子字符串。

sprintf('(?=(.{2,})(?:\\1){%s,})', thr-1)