繁体   English   中英

使用字符串数组创建最长的单词链

[英]Make Longest Possible Word Chain with String Array

我正在尝试制作一个程序,将一系列单词分类为最长的“链”(每个单词以前一个单词结尾的字母开头)。 一个示例链是Uta h - > H awai i - > I dah o - > O regon。

我一直试图解决这个问题大约2个小时了。 我一直在使用的方法是蛮力,试图生成所有可能的链,然后找到最长的链。 我遇到的问题是我无法弄清楚如何在找到链条时陷入困境。 我试着去查看StackOverflow上是否已经回答了这个问题,我确实找到了一个关于这个问题的回答问题,但它是在Python中,当我测试接受的解决方案时,它在大型列表上失败了。

这是一般的想法:

  var words = ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","New Hampshire","New Jersey","New Mexico","New York","North Carolina","North Dakota","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"];

function longestChain(wordArray) {
  var allChains = [];
  for(var x = 0; x < words.length; x++) {
    /* I'm completely lost here
       store all chains generated with this start in the allChains array
       each chain should be an array
       example: ["Utah","Hawaii","Idaho","Oregon","New York","Kentucky"]
    */
  }
  var max = [0,0];
  for(var x = 0; x < allChains.length; x++) {
    if(allChains[x].length > max[0]) {
      max[0] = allChains[x].length;
      max[1] = x;
    }
  }
  return allChains[max[1]];
}

所以基本上我需要一种方法来找到所有可能的链而不需要循环。

首先,这是一个最长的寻路问题。

如果图是双向的,那么解决方案就是NP难。 你必须使用递归或回溯来解决它。 如果输入大小很小,您也可以使用musking dp解决它。 有人已经基于递归共享了一个解决方案。

如果图是指向但非循环的,它有解决方案。 您可以使用拓扑排序等算法来解决它。 链接

但如果图是指向循环图,它的行为就像双向图。 所以解决方案很难。

您的问题是有向循环图。
例如,
设词= {“abc”,“cde”,“efa”}
通过使用这些字,如果我们制作图形,则字[0]将连接到字[1],字[1]将连接到字[2]而字[2]将连接到字[0]。
所以它创建了一个循环图。

下面的递归函数getChains()将为您的用例构建所有可能的链,并将它们存储在allChains变量中。

正如我在评论中提到的,这个问题感觉像是一个最长的路径问题 如果是这种情况,你不能比蛮力解决方案做得更好。 因此,如果单词数组将变大,则以下解决方案将变得非常慢,但对于给定单词,它将在几秒钟内运行。

 var words = ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","New Hampshire","New Jersey","New Mexico","New York","North Carolina","North Dakota","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"]; var allChains = []; var usedWords = []; var currentChain = []; getChains(currentChain, words, usedWords, allChains) for(var i = 0; i < allChains.length; i++){ document.write(allChains[i]) document.write("<br>") } function getChains(currentChain, words, usedWords, allChains){ var found = false; for(var x = 0; x < words.length; x++){ if((currentChain.length == 0 || currentChain[currentChain.length-1].slice(-1) == words[x].toLowerCase().charAt(0)) && !usedWords.includes(x)){ currentChain.push(words[x]); found = true; usedWords.push(x); getChains(currentChain, words, usedWords, allChains); } } if(!found){ allChains.push(currentChain.slice()); } currentChain.pop(); usedWords.pop(); } 

您可以将以相同字母开头和结尾的单词分开,然后将剩下的单词用于构建树。 然后获取最长的单词数组并尝试添加具有相同字母开头/结尾的单词。

 function getLongestWords(words) { function getTree(word, seen) { var last = word.slice(-1).toUpperCase(); if (!data[last]) return {}; return data[last].reduce(getChildren(seen.concat(word)), {}); } function getChildren(seen) { return function (r, w) { if (!seen.includes(w)) r[w] = getTree(w, seen); return r; }; } function getLength(array) { return array.reduce((l, { length }) => l + length, 0); } function getLongest(object, result = [], parts = []) { var keys = Object.keys(object); if (!keys.length) { if (getLength(parts) > getLength(result[0] || [])) { result.length = 0; result.push(parts); } else if (getLength(parts) === getLength(result[0])) { result.push(parts); } return result; } keys.forEach(k => getLongest(object[k], result, parts.concat(k))); return result; } var notSame = [], same = {}, data = words.reduce((r, w) => { var key = w[0], last = w.slice(-1); if (key === last.toUpperCase()) { same[key] = same[key] || { words: [], used: [] }; same[key].words.push(w); } else { r[key] = r[key] || []; r[key].push(w); notSame.push(w); } return r; }, {}), tree = notSame.reduce(getChildren([]), {}); return getLongest(tree).map((a, i) => { var key = a[0][0]; if (key in same && !same[key].used.includes(i)) { same[key].used.push(i); return same[key].words.concat(a); } return a.reduce((r, w) => { key = w.slice(-1).toUpperCase(); r.push(w); if (key in same && !same[key].used.includes(i)) { same[key].used.push(i); r.push(...same[key].words); } return r; }, []); }); } var words1 = ["Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"], words2 = ["Abc", "Cde", "Efa"]; console.log(getLongestWords(words1)); console.log(getLongestWords(words2)); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM