当前位置: 首页 > 知识库问答 >
问题:

如何从Trie中检索给定长度的随机单词

颜功
2023-03-14

我有一个简单的Trie,我用它来存储大约80k个长度为2-15的单词。它非常适合检查字符串是否是单词;然而,现在我需要一种获得给定长度的随机单词的方法。换句话说,我需要“getRandomWord(5)”来返回一个5个字母的单词,所有5个字母的单词都有相同的机会被返回。

我能想到的唯一方法是选择一个随机数并遍历树的宽度--首先,直到我通过了所需长度的那么多单词。有没有更好的办法做到这一点?

可能没必要,但这是我的trie代码。

class TrieNode {
    private TrieNode[] c;
    private Boolean end = false;

    public TrieNode() {
        c = new TrieNode[26]; 
    }

    protected void insert(String word) {
        int n = word.charAt(0) - 'A';
        if (c[n] == null)
            c[n] = new TrieNode();
        if (word.length() > 1) {
            c[n].insert(word.substring(1));
        } else {
            c[n].end = true;
        }
    }

    public Boolean isThisAWord(String word) {
        if (word.length() == 0)
            return false;
        int n = word.charAt(0) - 'A';
        if (c[n] != null && word.length() > 1)
            return c[n].isThisAWord(word.substring(1));
        else if (c[n] != null && c[n].end && word.length() == 1)
            return true;
        else
            return false;
    }
}
class TrieBranch {
    TrieNode node;
    int letter;
    int depth;
    public TrieBranch(TrieNode n, int l, int d) {
        letter = l; node = n; depth = d;
    }
}
class Dict {

    final static int maxWordLength = 13;    
    final static int lettersInAlphabet = 26;
    TrieNode trie;
    int lengthFrequencyByLetter[][];
    int totalLengthFrequency[];

    public Dict() {
        trie = new TrieNode();
        lengthFrequencyByLetter = new int[lettersInAlphabet][maxWordLength + 1];
        totalLengthFrequency = new int[maxWordLength + 1];
    }

    public String getRandomWord(int length) {
        // Returns a random word of the specified length from the trie
        // First, pick a random number from 0 to [number of words with this length]
        Random r = new Random();
        int wordIndex = r.nextInt(totalLengthFrequency[length]);

        // figure out what the first letter of this word would be
        int firstLetter = -1, totalSoFar = 0;
        while (totalSoFar <= wordIndex) {
            firstLetter++;
            totalSoFar += lengthFrequencyByLetter[firstLetter][length];
        }
        wordIndex -= (totalSoFar - lengthFrequencyByLetter[firstLetter][length]);

        // traverse the (firstLetter)'th node of trie depth-first to find the word (wordIndex)'th word
        int[] result = new int[length + 1];
        Stack<TrieBranch> stack = new Stack<TrieBranch>();
        stack.push(new TrieBranch(trie.getBranch(firstLetter), firstLetter, 1));
        while (!stack.isEmpty()) {
            TrieBranch n = stack.pop();
            result[n.depth] = n.letter;

            // examine the current node
            if (n.depth == length && n.node.isEnd()) {
                wordIndex--;
                if (wordIndex < 0) {
                    // search is over
                    String sResult = "";
                    for (int i = 1; i <= length; i++) {
                        sResult += (char)(result[i] + 'a');
                    }
                    return sResult;
                }
            }

            // handle child nodes unless they're deeper than target length
            if (n.depth < length) {
                for (int i = 25; i >= 0; i--) {
                    if (n.node.getBranch(i) != null)
                        stack.push(new TrieBranch(n.node.getBranch(i), i, n.depth + 1));
                }
            }
        }
        return "failure of some sort";
    }
}

共有1个答案

孟树
2023-03-14

为了确保你有一个均匀的机会得到每个5个字母的单词,你需要知道有多少5个字母的单词在你的树。因此,在构建树时,将单词的长度添加到两个计数器中:总频率计数器和字母频率计数器:

int lengthFrequencyByLetter[letterIndex][maxWordLength-1]
int totalLengthFrequency[maxWordLength-1]

如果你有4000个5个字母的单词,其中213个以“d”开头,那么

lengthFrequencyByLetter[3][4] = 213

totalLengthFrequency[4] = 4000

在将所有内容添加到树之后。(字母“A”是0,“B”是1,……“Z”是25。)

从这里,您可以搜索给定长度n的第1个单词,其中n是从均匀随机分布中挑选的随机整数,范围为(0,totallengthfrequence[length-1])。

lengthFrequencyByLetter[0][4]
lengthFrequencyByLetter[1][4]
lengthFrequencyByLetter[2][4]
lengthFrequencyByLetter[3][4]
 类似资料:
  • 上面的答案解释了如何选择第一个角色,但我很困惑之后我们将如何进行。我想要长度为L的词,但当我开始遍历树时,我不知道正在遍历的树枝是否有深度L。 词典

  • 本文向大家介绍Python生成给定长度的随机字符串,包括了Python生成给定长度的随机字符串的使用技巧和注意事项,需要的朋友参考一下 在本文中,我们将看到如何生成具有给定长度的随机字符串。这在创建需要随机性的随机密码或其他程序时很有用。 random.choices 随机模块中的choices函数可以产生字符串,然后可以将其连接以创建给定长度的字符串。 示例 输出结果 运行上面的代码给我们以下结

  • 问题内容: 我正在学习Java,并且遇到了和的问题。 我有一个称为的对象,该对象具有从另一个名为的类创建的对象的数组列表。 我需要一种方法,其中返回item列表中一个对象的所有信息。 该随意选择的需求。 当我尝试编译时,出现错误,指出System.out.println行说.. 问题答案: 是一个方法,调用在你的return语句之后,因此由于无法访问而无法进行编译。 可能希望将其重写为:

  • 如果我正确地看到了这一点,那么trie中的所有叶节点都将拼写出整个单词,所有父节点都包含最终叶节点之前的字符。因此,如果我有一个名为DigitalTreeNode的类,其定义为 如果我想实现一个返回trie中最长单词的方法,是否只需要在每个叶节点查找最长单词?如何实现方法,例如: 我猜它涉及到设置一个最长的字符串变量,递归地遍历每个节点,并检查它是否是一个单词,如果它是一个单词,并且它的长度大于最

  • 问题内容: 我有一个带有这样的树的firebase数据库 等等… 在我的应用程序中,用户下载项目,而项目下载时,电视主题将从URL播放。当单个项目发生价值事件时,我可以使其正常运行。我希望它从列表中随机选择一个值。如何做到这一点? 由于我的应用程序不包含任何内容,因此编辑可以使用回收视图方法 这是我的单项代码 问题答案: 要解决此问题,请使用以下代码行: 然后使用循环使用随机数提取该值:

  • 问题内容: 在Go语言中,我只需要一个随机的字符串(大写或小写),没有数字。最快和最简单的方法是什么? 问题答案: Paul的解决方案提供了一个 简单的 通用解决方案。 问题要求 “最快,最简单的方法” 。让我们也讨论 最快的 部分。我们将以迭代的方式得出最终的最快的代码。对每个迭代进行基准测试可以在答案的结尾处找到。 所有解决方案和基准代码都可以在GoPlayground上找到。Playgrou