Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 一种有效的短语字谜算法_String_Algorithm_Anagram - Fatal编程技术网

String 一种有效的短语字谜算法

String 一种有效的短语字谜算法,string,algorithm,anagram,String,Algorithm,Anagram,在给定字符串的情况下,生成短语字谜的有效方法是什么 我试图解决的问题 假设您有一个包含n个单词的单词列表。给定一个输入字符串,比如“peanutbutter”,生成所有短语的字谜。一些竞争者是:豌豆坚果黄油,但10喷发,等等 我的解决方案 我有一个trie,它包含给定单词列表中的所有单词。给定一个输入字符串,我计算它的所有排列。对于每个置换,我都有一个递归解决方案(类似于)来确定特定置换字符串是否可以分解为单词。例如,如果花生酱的一个排列是“abuttenerupt”,我就用这个方法把它分成“a

在给定字符串的情况下,生成短语字谜的有效方法是什么

我试图解决的问题

假设您有一个包含n个单词的单词列表。给定一个输入字符串,比如“peanutbutter”,生成所有短语的字谜。一些竞争者是:豌豆坚果黄油,但10喷发,等等

我的解决方案

我有一个trie,它包含给定单词列表中的所有单词。给定一个输入字符串,我计算它的所有排列。对于每个置换,我都有一个递归解决方案(类似于)来确定特定置换字符串是否可以分解为单词。例如,如果花生酱的一个排列是“abuttenerupt”,我就用这个方法把它分成“a但10个喷发”。我使用trie来确定字符串是否为有效单词

什么最糟糕

我的问题是,因为我计算了所有排列,所以对于长度超过10个字符的短语,我的解决方案运行得非常慢,这是一个很大的缺点。我想知道是否有一种方法可以用另一种方式做到这一点。
像这样的网站可以在不到一秒钟的时间内完成这项工作,我很想知道它们是如何做到的。

与两阶段解决方案不同,在两阶段解决方案中,您可以生成排列,然后尝试将它们分解为单词,您可以通过在递归生成排列时检查有效单词来加快速度。如果在任何一点上,你当前的部分完全排列与任何有效的单词都不对应,那么就到此为止,不要再重复。这意味着您不会浪费时间生成无用的排列。例如,如果生成“tt”,则不需要排列“peanubuter”并将所有排列附加到“tt”,因为没有以tt开头的英语单词

假设您正在进行基本的递归置换生成,请跟踪您生成的当前部分单词。如果在任何时候它是一个有效的字,您可以输出一个空格并开始一个新字,然后递归地排列剩余的字符。您还可以尝试将剩余的每个字符添加到当前部分单词中,并且仅当这样做会产生有效的部分单词(即,存在以这些字符开头的单词)时才递归

类似这样的代码(伪代码):

你可以这样称呼它

 generateAnagrams("", "", "peanutbutter");
通过在trie中传递与当前部分完成的单词对应的节点,以及将
currentWord
作为字符串传递,可以进一步优化该算法。这将使您的
isValidPartialWord
检查更快


您可以通过将
isValidWord
检查更改为仅当单词按升序(大于或等于)字母顺序与前一个单词输出相比时才返回true来强制唯一性。您可能还需要在结尾再次检查重复,以捕获可以输出两个相同单词的情况。

您的问题可以分解为两个子问题:

  • 查找使用输入字符串中所有字符的单词组合
  • 查找第一个子问题中找到的单词的所有排列
  • 子问题#2是一个基本算法,您可以在大多数编程语言中找到现有的标准实现。让我们关注子问题1

    首先将输入字符串转换为“字符池”。我们可以将字符池实现为数组
    oc
    ,其中
    oc[c]
    =字符c的出现次数

    然后,我们使用回溯算法查找适合字符池的单词,如以下伪代码所示:

     void generateAnagrams(String partialAnagram, String currentWord, String remainingChars)
     {
          // at each point, you can either output a space, or each of the remaining chars:
    
          // if the current word is a complete valid word, you can output a space
          if(isValidWord(currentWord))
          {
               // if there are no more remaining chars, output the anagram:
               if(remainingChars.length == 0)
               {
                   outputAnagram(partialAnagram);
               }
               else
               {
                   // output a space and start a new word
                   generateAnagrams(partialAnagram + " ", "", remainingChars);
               }
          }
    
          // for each of the chars in remainingChars, check if it can be
          // added to currentWord, to produce a valid partial word (i.e.
          // there is at least 1 word starting with these characters)
          for(i = 0 to remainingChars.length - 1)
          {
              char c = remainingChars[i];
              if(isValidPartialWord(currentWord + c)
              {
                  generateAnagrams(partialAnagram + c, currentWord + c,
                      remainingChars.remove(i));
              }
          }
     }
    
    result = empty;
    
    function findAnagram(pool)
      if (pool empty) then print result;
      for (word in dictionary) {
        if (word fit in charpool) {
          result = result + word;
          update pool to exclude characters in word;
          findAnagram(pool);
    
          // as with any backtracking algorithm, we have to restore global states
          restore pool;
          restore result;
        }
      }
    }
    
    注意:如果我们通过值传递charpool,那么就不必恢复它。但是因为它很大,我更喜欢通过引用来传递它

    现在,我们删除冗余结果并应用一些优化:

    function findAnagram(charpool, minDictionaryIndex)
      pool_bitmask <- bitmask(charpool);
      if (pool empty) then print result;
      for (word in dictionary AND word's index >= minDictionaryIndex) {
        // bitmask of every words in the dictionary should be pre-calculated
        word_bitmask <- bitmask(word)
        if (word_bitmask contains bit(s) that is not in pool_bitmask)
          then skip this for iteration
        if (word fit in charpool) {
          result = result + word;
          update charpool to exclude characters in word;
          findAnagram(charpool, word's index);
    
          // as with any backtracking algorithm, we have to restore global states
          restore pool;
          restore result;
        }
      }
    }
    
    • 假设字典中A在B之前。如果我们选择第一个单词是B,那么我们不必在下面的步骤中考虑单词A,因为那些结果(如果我们取a)已经在A被选择为第一个单词

    • 的情况下。
    • 如果字符集足够小(最好小于64个字符),我们可以使用位掩码快速过滤池中无法容纳的字。位掩码屏蔽字中的哪个字符,无论它出现多少次

    更新伪代码以反映这些优化:

    function findAnagram(charpool, minDictionaryIndex)
      pool_bitmask <- bitmask(charpool);
      if (pool empty) then print result;
      for (word in dictionary AND word's index >= minDictionaryIndex) {
        // bitmask of every words in the dictionary should be pre-calculated
        word_bitmask <- bitmask(word)
        if (word_bitmask contains bit(s) that is not in pool_bitmask)
          then skip this for iteration
        if (word fit in charpool) {
          result = result + word;
          update charpool to exclude characters in word;
          findAnagram(charpool, word's index);
    
          // as with any backtracking algorithm, we have to restore global states
          restore pool;
          restore result;
        }
      }
    }
    
    函数findAnagram(charpool,mindictionalyindex)
    
    pool_bitmask我认为使用分部词是个好主意。我想我可以在trie中查找:检查是否有一个词以部分词开头。谢谢