我试图提出一种算法,用于确定句子中所有单词组合的组合(不破坏单词的顺序)。
例如用这个句子:“测试用例短语” 不同的组合(分割任意数量的空间)将是:
['the test case phrase']
['the' , 'test case phrase']
['the test' , 'case phrase']
['the test case' , 'phrase']
['the' , 'test' , 'case phrase']
['the test' , 'case' , 'phrase']
['the' , 'test case', 'phrase']
['the' , 'test' , 'case' , 'phrase']
我最初是在考虑排列,但据我所知,这可能是我是否在寻找组合的重新排序组合。
我觉得这里有一个数学原理在工作,但我只是无法动弹……
仅供参考:我正在编写测试用例,并计划用Javascript实现解决方案
答案 0 :(得分:3)
可以通过应用Star and Bars
的概念来解决您的问题基本上,对于我们给出的示例,我们有四个词。我们不在乎它们是不同的,只是它们是语言。这些将是我们的明星。现在,用四个词,我们之间有3个空格,逗号可以分开(我们的小节)。我们最初从零个逗号开始,一直到最多三个逗号。
对于(逗号数)= 0,我们有:
3! / (0! (3 - 0) !) = 1
对于(逗号数)= 1,我们有:
3! / (1! (3 - 1) !) = 3
对于(逗号数)= 2,我们有:
3! / (2! (3 - 2) !) = 3
对于(逗号数)= 3,我们有:
3! / (3! (3 - 3) !) = 1
这总共提供了1 + 3 + 3 + 1 = 8
个单词组合。
要在算法上进行攻击,您可以简单地遍历空格的每个组合,并在输入时插入逗号。这不应该那么困难。
我不了解javascript,因此我将在R
中给出代码(注意,我不推荐在R
中使用以下编码样式。.我这样做是为了更加透明其他语言):
words = c("the test case phrase")
## trivial case.. no commas
listOfWords = list(words)
## split on spaces
myWords = strsplit(words, " ")[[1]]
count = 1
for (i in 1:3) {
myCombs = combn(3, i)
for (j in 1:ncol(myCombs)) {
tempWords = myWords
for (k in 1:nrow(myCombs)) {
tempWords[myCombs[k, j]] = paste(c(tempWords[myCombs[k, j]], ","), collapse = "")
}
count = count + 1
listOfWords[[count]] = paste(tempWords, collapse = " ")
}
}
这是输出:
listOfWords
[[1]]
[1] "the test case phrase"
[[2]]
[1] "the, test case phrase"
[[3]]
[1] "the test, case phrase"
[[4]]
[1] "the test case, phrase"
[[5]]
[1] "the, test, case phrase"
[[6]]
[1] "the, test case, phrase"
[[7]]
[1] "the test, case, phrase"
[[8]]
[1] "the, test, case, phrase"
答案 1 :(得分:3)
作为javascript中的回溯递归函数,该作品非常干净。您遍历数组,并使用i到i-1的第一部分构建每个项目,然后在每个循环中递归其余部分,同时将结果添加到数组res
:
let str = "the test case phrase"
function mix(arr, res, start = []) {
for (let i = 1; i < arr.length; i++) { // You don't need a base case because when length is 0 the loop won't run
let rest = arr.slice() // make a copy so we don't mess up the input
let head = rest.splice(0, i).join(" ") // take the head + the rest for o to i
res.push([...start, head, rest.join(' ')]) // add it as an entry
mix(rest, res, [...start, head]) // recurse on the rest
}
return res
}
let r = mix(str.split(" "), [str]) // we don't need to calculate the original string, so just start with it.
console.log(r.join('\n'))