检查是否存在任何数量的字符串组合

时间:2016-07-27 03:26:50

标签: javascript

我正在解决一个难题,我知道如何解决这个问题,但我想要一些指导和提示。

假设我有以下内容,给定n个字输入,以及m个没有空格的单词组合,我将有如下的一些功能。

    4
    this
    is
    my
    dog
    5
    thisis        // outputs 1
    thisisacat    // 0, since a or cat wasnt in the four words
    thisisaduck   // 0, no a or cat
    thisismy      // 1 this,is,my is amoung the four words
    thisismydog   // 1

我的想法

首先我想要做的是将第一个单词存储到数组中。之后,我检查这些单词中是否有任何单词是这5个单词的第一个单词

示例:检查this是否在第一个单词thisis中。它是!太棒了,现在从this删除thisis只是is,现在删除对应于该等式的原始字符串并继续迭代左边(现在is,my,dog是可用的)。如果我们可以继续这个过程,直到我们得到一个空字符串。我们返回1,否则返回0!

我的想法是否正确?我认为这将是一个很好的方法(顺便说一下,我想在javascript中实现这个)

3 个答案:

答案 0 :(得分:2)

从长到短的单词排序可能在某些情况下有助于更快地找到解决方案,但这不是保证。如果最长的单词,则包含最长单词的句子可能只有一个解决方案。

以此测试案例为例:

单词:工具箱,凳子,拳击手
句子:凳子

如果将“工具箱”作为该句子中的单词,则其余字符不能与其他有效单词匹配。然而,有一个解决方案,但只有在不使用“工具箱”这个词时才会使用。

具有正则表达式的解决方案

当正则表达式被允许作为解决方案的一部分时,它非常简单。对于上面的示例,正​​则表达式将是:

^(toolbox|stool|boxer)*$

如果一个句子与该表达式匹配,那么它就是一个解决方案。如果没有,那么不是。这非常简单,并不需要算法。全部由正则表达式解释器完成。这是一个片段:

var words = ['this','is','a','string'];
var sentences = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg']; 

var regex = new RegExp('^(' + words.join('|') + ')*$');
sentences.forEach(sentence => {
    // search returns a position. It should be 0:
    console.log(sentence + ': ' + (sentence.search(regex) ? 'No' : 'Yes'));
});

但是在算法挑战中使用正则表达式感觉就像作弊:你并没有真正编写算法,而是依靠正则表达式实现为你完成这项工作。

没有正则表达式

您可以使用此算法:首先检查输入句子开头是否匹配单词,如果是,请从中删除第一个匹配项。然后对句子的剩余部分重复此操作。如果可以重复此操作直到没有剩余字符,那么您就有了解决方案。

如果剩下的字符无法与任何单词匹配......好吧,那么你无法断定那句话没有解决方法。可能是某些早期的单词选择是错误的,并且有另一种选择。因此,为了应对这种情况,您的算法可以回溯并尝试其他词语。

这个原则可以通过递归来实现。为了获得记忆效率,您可以保留原始句子,并在该句子中使用索引。

该算法以箭头函数testString

实现

var words = ['this','is','a','string'];
var sentences = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg']; 

var testString = (words, str, i = 0) =>
    i >= str.length || words.some( word =>
        str.substr(i, word.length) == word && testString(words, str, i + word.length)
    );
    
sentences.forEach(sentence => {
    console.log(sentence + ': ' + (testString(words, sentence) ? 'Yes' : 'No'));
});

或者,非箭头函数语法相同:

var words = ['this','is','a','string'];
var sentences = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg']; 

var testString = function (words, str, i = 0) {
    return i >= str.length || words.some(function (word) {
        return str.substr(i, word.length) == word 
            && testString(words, str, i + word.length);
    });
}
sentences.forEach(function (sentence) {
    console.log(sentence + ': ' + (testString(words, sentence) ? 'Yes' : 'No'));
});

...没有some()forEach()或三元运营商:

var words = ['this','is','a','string'];
var sentences = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg']; 

function testString (words, str, i = 0) {
    if (i >= str.length) return true;
    for (var k = 0; k < words.length; k++) {
         var word = words[k];
         if (str.substr(i, word.length) == word 
             && testString(words, str, i + word.length)) {
              return true;
         }
    }
}

for (var n = 0; n < sentences.length; n++) {
    var sentence = sentences[n];
    if (testString(words, sentence)) {
        console.log(sentence + ': Yes');
    } else {
        console.log(sentence + ': No');
    }
}

答案 1 :(得分:1)

取4个字,把它们放到正则表达式中。 使用该正则表达式来拆分每个字符串。 取结果数组的长度(减去一个初始长度为1)。

var size = 'thisis'.split(/this|is|my|dog/).length - 1

或者,如果您的单词列表是数组

var search = new RegExp(words.join('|'))
var size = 'thisis'.split(search).length - 1

无论哪种方式,您都要按照已定义的单词列表拆分字符串。

您可以按长度对单词进行排序,以确保首先匹配较大的单词

words.sort(function (a, b) { return b.length - a.length })

答案 2 :(得分:0)

这是任何有兴趣的人的解决方案

var input = ['this','is','a','string']; // This will work for any input, but this is a test case
var orderedInput = input.sort(function(a,b){
    return b.length - a.length;
});
var inputRegex = new RegExp(orderedInput.join('|'));
// our combonation of words can be any size in an array, just doin this since prompt in js is spammy
var testStrings = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg']; 
var foundCombos  = (regex,str) => !str.split(regex).filter(str => str.length).length;
var finalResult = testStrings.reduce((all,str)=>{
    all[str] = foundCombos(inputRegex,str);
    if (all[str] === true){
        all[str] = 1;
    }
    else{
        all[str] = 0;
    }
    return all;
},{});
console.log(finalResult);