请看这个JSFiddle:https://jsfiddle.net/nu69kxyq/
这个JS接受输入文本文件,每行包含一个单词。 JS函数找到最长和第二长的复合词(仅由文件中的其他词组成)和这些复合词的总数。
这是我正在使用的确切输入:
cat
cats
catsdogcats
dog
dogcatsdog
hippopotamuses
rat
ratcatdogcat
输出应为:
ratcatdogcat <-- longest compound word (12 characters)
catsdogcats <-- second longest compound word (11 characters)
3 <-- total number of compound words in a file
复合词的总数是3,因为catdogcats,dogcatsdog,ratcatdogcat。
我首先接受所有单词,然后在wordsList
中对其进行排序。然后我在wordDict
中创建一个单词哈希表供参考(以检查复合词):
var wordsList = list.sort(function(a, b) {
return a.length - b.length; //sort words by length ascending
});
var wordDict = list.reduce(function(words, value, index) { //hash table from text file data
words[value] = true;
return words;
},{});
var isConcat = function(word) {
for (var i = word.length; i > -1; i--){
var prefix = word.slice(0,i);
var suffix = word.slice(i, word.length);
if (wordDict[prefix] === true){ //????? THIS IS ALWAYS FALSE EVEN WHEN THE KEY'S VALUE IS TRUE!!!
if (suffix.length === 0) {
return true; //all suffix are prefixes. word is concatenated.
}
return isConcat(suffix); //continue breaking remaining suffix into prefix if possible
}
}
return false;
};
问题出在isConcat
,当我检查wordDict[prefix]
以查看密钥的值是否为真时,它始终为false。即使它应该是真的!我尝试单步执行代码,当'word'键的键值为'true'时,if (wordDict[prefix] === true)
语句仍然不执行,因为它认为它是错误的。使用data.split("\n");
,我能够读取文本文件并将其放入数组中。没问题。出了什么问题?
注意:我尝试使用var list = data.match(/\w+/g);
代替var list = data.split("\n");
将所有字母数字字符匹配为单词,而不是按新行分割它们,并且函数有效(wordDict [prefix]按预期工作)。但是当我传入超过150,000个文本单词的文本文件时,这个正则表达式会跳过一些单词。我想我需要使用data.split("\n")
。这里出了什么问题?
答案 0 :(得分:1)
这是一个isConcat
的工作实现,它不是递归的,因此不会出现堆栈溢出错误的问题:
function isConcat(word) {
for (var i = word.length; i >= 0; i--) {
var prefix = word.slice(0, i);
var suffix = word.slice(i);
if (wordDict[prefix]) {
if (suffix.length === 0) {
return true; // all suffix are prefixes. word is concatenated.
} else {
// "restart" with suffix as the word
word = suffix;
i = word.length+1;
}
}
}
return false;
}
它基本上做同样的事情,除了它循环/重启而不是递归。 请注意,这不仅会匹配复合词,还会匹配与列表中的单词完全匹配的单词(只有一个单词的复合词)。