生成给定字符串的所有可能字母组合的算法,最多2个字母

时间:2010-03-13 18:10:43

标签: actionscript-3 algorithm permutation

生成给定字符串的所有可能字母组合的算法,最少为2个字母

尝试在AS3中创建一个Anagram解算器,例如这里找到的那​​个:

http://homepage.ntlworld.com/adam.bozon/anagramsolver.htm

我在绕着不同长度的琴弦生成所有可能的字母组合时遇到了问题。如果我只生成一个固定长度的排列,对我来说这不会是一个问题...但我希望减少字符串的长度并从原始字母集中获取所有可能的排列最大长度小于原始字符串的字符串。例如,假设我想要一个2的字符串长度,但我有一个3字母的字符串“abc”,输出将是:ab ac ba bc ca cb。

理想情况下,算法会生成一个完整的可能组合列表,从原始字符串长度开始,最小字符串长度为2.我感觉可能有一个小的递归算法来做到这一点,但不能包装我的大脑围绕它。我在AS3工作。

谢谢!

5 个答案:

答案 0 :(得分:7)

为了编写您链接的anagram解算器,您要求的算法不是必需的。它也非常昂贵。

让我们看一下像MONKEY这样的6个字母的单词。这个单词的所有6个字母都不同,所以你要创建:

  • 6 * 5 * 4 * 3 * 2 * 1个不同的6个字母的单词
  • 6 * 5 * 4 * 3 * 2个不同的5个字母的单词
  • 6 * 5 * 4 * 3个不同的4个字母的单词
  • 6 * 5 * 4个不同的3个字母的单词
  • 6 * 5个不同的2个字母的单词
  • 总共1950字

现在,大概你并没有试图将所有1950个单词(例如'OEYKMN')吐出来作为字谜(他们是,但他们中的大多数也是胡言乱语)。我猜你有一个法律英语词典,你只想检查这些词是否是查询词的字谜,可以选择不使用所有字母。

如果是这种情况,那么问题很简单。

要确定2个单词是否是彼此的字谜,您需要做的就是计算每个字母的使用次数,并比较这些数字!

我们将自己限制为只有26个字母A-Z,不区分大小写。你需要做的是编写一个函数countLetters,它接受​​一个单词并返回一个包含26个数字的数组。数组中的第一个数字对应于单词中字母A的计数,第二个数字对应于B的计数等。

然后,如果每个W1 W2,则countLetters(W1)[i] == countLetters(W2)[i]i这两个词就是精确的字谜!也就是说,每个单词使用的每个字母的次数完全相同!

对于我称之为子字谜(MONEYMONKEY)的子字谜,W1W2的子字谜countLetters(W1)[i] <= countLetters(W2)[i] if {{每个i 1}}!也就是说,子字谜可以使用较少的某些字母,但不能更多!

(注意:MONKEY也是MONKEY)的子字谜。


这应该给你一个足够快的算法,给定一个查询字符串,你需要做的就是读一遍字典,比较每个字的字母数字数组和查询字的字母数字数组。你可以做一些小的优化,但这应该足够好了。

或者,如果您想获得最佳性能,可以预先处理字典(事先已知)并创建子字母关系的有向非循环图。

以下是此类图表的一部分用于说明:

 D=1,G=1,O=1  ----------> D=1,O=1
  {dog,god}   \            {do,od}
               \
                \-------> G=1,O=1
                           {go}

基本上每个节点都是一个桶,用于所有具有相同字母数组的单词(即它们是精确的字谜)。如果N1的数组为N2(如上所定义)N2的数组(您可以执行传递减少),那么会有一个从<=N1的节点存储最少量的边缘。)

然后列出单词的所有子字谜,您所要做的就是找到与其字母计数数组对应的节点,并递归浏览从该节点可到达的所有节点。他们所有的桶都包含子字谜。

答案 1 :(得分:3)

以下js代码将在n个字母单词中找到所有可能的“单词”。当然,这并不意味着它们是真实的单词,但确实为您提供了所有组合。在我的机器上,7字母单词需要大约0.4秒,9字母单词需要15秒(如果没有重复的字母,则可达到近百万种可能性)。然而,那些时候包括在字典中查找并找到哪些是真实的单词。

var getWordsNew=function(masterword){
var result={}
 var a,i,l;
function nextLetter(a,l,key,used){
     var i;
    var j;
    if(key.length==l){
        return;
    }
    for(i=0;i<l;i++){
        if(used.indexOf(""+i)<0){
            result[key+a[i]]="";
            nextLetter(a,l,key+a[i],used+i);
        }
    }
 }
a=masterword.split("");
  l=a.length;
for (i = 0; i < a.length; i++) {
    result[a[i]] = "";
    nextLetter(a, l, a[i], "" + i)
}
return result;
}

的完整代码

Code for finding words in words

答案 2 :(得分:0)

你想要一种安排。如果你熟悉排列算法,那么你知道你有一个检查,看看你什么时候生成了足够多的数字。只需改变这个限制:

我不知道AS3,但这是伪代码:

st = an array
Arrangements(LettersInYourWord, MinimumLettersInArrangement, k = 1)
  if ( k > MinimumLettersInArrangements )
  {
    print st;
  }

  if ( k > LettersInYourWord )
    return;      

  for ( each position i in your word that hasn't been used before )
    st[k] = YourWord[i];
    Arrangements(<same>, <same>, k + 1);

表示“abc”和安排(3,2,1);这将打印:

ab
abc
ac
acb
...

如果你想要那些先有三个,然后有两个,请考虑这个:

st = an array
Arrangements(LettersInYourWord, DesiredLettersInArrangement, k = 1)
  if ( k > DesiredLettersInArrangements )
  {
    print st;
    return
  }

  for ( each position i in your word that hasn't been used before )
    st[k] = YourWord[i];
    Arrangements(<same>, <same>, k + 1);

然后为“abc”拨打Arrangements(3, 3, 1);,然后拨打Arrangements(3, 2, 1);

答案 3 :(得分:0)

您可以通过查找字母完整图表中的所有路径来生成字母表中的所有单词。您可以通过从每个字母进行深度优先搜索并在每个点返回当前路径来查找该图中的所有路径。

答案 4 :(得分:0)

有简单的O(N),其中n是词汇量的大小。 只需在词汇表或更好的单词中对每个单词中的字母进行排序,创建它们的二进制掩码,然后比较您拥有的英文字母。

相关问题