如何在R中检查给定字符串是否为另一个给定字符串的循环旋转?例如: 1234
通过两次偏移是 3412
的循环旋转。但我想检查一个字符串是否与另一个字符串在任意数量的移位下循环等价。
根据Henrik的评论,测试(i) nchar
是否相等以及(ii)如果一个向量在复制第二个后成为其一部分似乎是足够的:
ff = function(x, y) (nchar(y) == nchar(x)) && (grepl(y, strrep(x, 2), fixed = TRUE))
ff("3412", "1234")
#[1] TRUE
strrep
无法分配所需的内存。 - alexis_lazy
的长度最大,则x
只能有一半的字节。总共,x
和y
可以拥有最多3 * 10 ^ 9个字节,大约相当于3 GB的内存。也许,Unicode可能需要更多的内存,但可用内存可能不是您方法的阻碍者。 - Uwesub
解决方案:cycrotT = function(s1,s2) {
if (nchar(s1)!=nchar(s2)) {
return(FALSE) }
for (i in 1:nchar(s2)) {
if (s1==s2) {
return(TRUE) }
# Move the first character to the end of the string
s2 = sub('(.)(.*)', '\\2\\1', s2)
}
return(FALSE)
}
> cycrotT("1234567", "1324567")
# [1] FALSE
> cycrotT("1234567", "4567123")
# [1] TRUE
> cycrotT("1234567", "1234568")
# [1] FALSE
一种更长但或许更清晰的方法如下:
cyclic_index <- function(string1, string2) {
## gather info about the first string
chars <- el(strsplit(string1, ""))
length <- length(chars)
vec <- seq_len(length)
## create a matrix of possible permutations
permutations <- data.frame(matrix(NA, nrow = length, ncol = length + 1))
names(permutations) <- c("id", paste0("index", vec))
permutations$id <- vec
## calculate the offset indices
for (r in vec)
permutations[r, vec + 1] <- (vec + r - 1) %% (length)
## a %% a = 0 so reset this to a
permutations[permutations == 0] <- length
## change from indices to characters
permutations[ , vec + 1] <- sapply(vec, function(x) chars[unlist(permutations[x, vec + 1])])
## paste the characters back into strings
permutations$string <- sapply(vec, function(x) paste0(permutations[x , vec + 1], collapse = ''))
## if string2 is a permutation of string1, return TRUE
return(string2 %in% permutations$string)
}
cyclic_index("jonocarroll", "carrolljono")
#> TRUE
cyclic_index("jonocarroll", "callorrjono")
#> FALSE
cyclic_index("1234567", "4567123")
#> TRUE
grepl
函数匹配另一个向量,或者使用grepl(y, strrep(x, 2)) || grepl(x, strrep(y, 2))
的替代方法。 - alexis_laznchar
的检查是否足够呢?nchar(x) == nchar(y) & grepl(pattern = y, x = strrep(x, 2))
。想发表一篇答案吗? - Henrik