【问题标题】:Finding the longest word given a trie dictionary and letters查找给定特里字典和字母的最长单词
【发布时间】:2014-05-04 10:58:18
【问题描述】:

对于我正在开发的单词构建游戏,我有一个可以存储字典中所有可能单词的 trie。目前大约有 179,000 个。

根据游戏的运作方式,有一个 5x5(或未来可能更大,取决于该问题的解决方案的效率如何)字母网格。玩家和 PC 轮流从这些字母中生成单词,根据字母和单词的长度获得分数(字母估值类似于 Scrabble,但这并不重要)。每当玩家说出一个单词时,这些字母就会从板上移除,并一直持续到无法说出单词为止,此时网格会重置(并且该回合的获胜者将获得奖金)。

问题是这样的:给定一个 5x5 的字母网格和字典树,我如何才能有效地确定最长的单词或所有可能单词的列表?请注意,字母不需要相互接触即可使用;任何网格的字母都可以。

我能想到的唯一方法本质上是在树上做一个 BFS,当下一个字母不在网格中时修剪它,但这对我来说似乎不是很有效,因为它必须尝试对于网格中的每个字母。有没有更好的方法来做到这一点?

【问题讨论】:

  • 您是否尝试过暴力破解方法并且性能无法接受?
  • 考虑到您要执行的操作,您确定使用 trie 是合适的数据结构吗?
  • @Pete:我还没有尝试过,但这将是阶乘时间。最初的完整 5x5 网格大约有 25 个!检查的可能性——效率太低了。
  • @ct_:我不能 100% 确定,但这是我能想到的最好的……还有其他建议吗?
  • @DanielBurnett 我认为在现实中蛮力方法不会接近 25! - 你不会期望有很多 25 个字母的单词。当然,编写该算法来测试它并不难——至少它提供了一个最坏情况的基准来测试其他方案,并且还为测试它们的正确性提供了参考。

标签: c++ search dictionary trie


【解决方案1】:

找到“最佳”词总是需要在 trie 中进行一些搜索。但是 trie 并不是一个糟糕的结构。

但是,您必须执行以下操作:

  1. 从你的板上选择一封信。
  2. 在树中找到当前“单词”的节点。
  3. 在黑板上再选一个字母。
  4. 从第 2 步开始重复,直到:找不到单词或在板上的字母中找不到单词。
  5. 记住您找到的单词的“分数”。
  6. 对板上的所有(唯一?)起始字母重复此过程。

您可能想检查您是否“以前尝试过此序列”,但我不确定这是否有多大好处。

为了使与计算机竞争的竞争对手相当公平,您可能希望限制计算机进行的尝试次数,因为在这种情况下人类可能永远无法战胜计算机。

【讨论】:

    【解决方案2】:

    我想出了一个算法,它在整个游戏中执行 O(n) 操作,其中 n 是字典的大小。不过,它使用了额外的数据结构,而且很可能简单的暴力破解就足够了。如果性能确实是个问题,请继续阅读。

    考虑可以使用黑板上的字母生成的一组单词。在整个游戏过程中,随着字母从棋盘上移除,单词将从该集合中移除。

    可以通过扫描字典来确定初始单词集。其字母构成板上字母子集的单词是有效的。有很多方法可以对此进行测试,例如将单词的排序字母与黑板上的排序字母进行比较或创建字母频率表并进行比较。

    当一个字母被移除时,该字母出现的次数与该字母被移除前在棋盘上出现的次数相同的单词必须从集合中移除。例如,如果棋盘有两个 e 并删除了一个,则只有恰好有两个 e 的单词需要从集合中删除。

    使用链表可以有效地维护单词集。对于得分最高的单词的恒定时间访问,可以在开始时使用 O(n) 排序算法对列表进行排序,例如pigeonhole sort。从列表中删除节点不会打乱顺序。

    为了有效删除具有一定字母频率的所有单词,对链表节点的引用存储在二维数组中。数组的条目 (x, n) 包含对所有节点的引用,这些节点的单词恰好出现 n 个字母 x

    例如,对包含单词 "eye" 的节点的引用将存储在条目 ('e', 2)('y' , 1) 的数组。当板上有两个 e 并且一个被删除时,条目 ('e', 2) 中的所有节点都从链表中删除。如果一个词已经被删除,它会被忽略。

    从链表中删除一个节点是在恒定时间内完成的,整个游戏中每个单词最多可以删除一次(并且可能最多有25次额外的删除尝试),使得整个过程O( n).

    【讨论】:

    • 我从来没有想过要这样做!当我有机会时,我会对其进行测试,但似乎它应该可以工作。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多