给定一个字典和字母,找出最长的单词
Finding the longest word given a trie dictionary and letters
对于我正在开发的一款单词构建游戏,我有一个tree,用于存储字典中所有可能的单词。目前约为17.9万。
游戏的运作方式是,有一个5x5的字母网格(未来可能会更大,取决于这个问题的解决方案的效率)。玩家和PC轮流从这些字母中创造单词,根据字母和单词的长度获得分数(字母的估值类似于《Scrabble》,但这并不重要)。每当玩家创造一个单词时,这些字母就会从棋盘上移除,直到没有单词可以创造,此时网格将被重置(并且这一轮的获胜者将获得奖金)。
问题是这样的:给定一个5x5的字母网格和那个字典树,我如何有效地确定可以制作的最长单词或所有可能的单词列表?请注意,这些字母不需要相互接触才能使用;任何格子的字母都可以。
我能想到的唯一方法就是在树上做一个BFS,当下一个字母不在网格中时修剪它,但这对我来说似乎不是很有效,因为它必须对网格中的每个字母进行尝试。有更好的方法吗?
找到"最佳"单词总是需要在树中进行一些搜索。但是,对于执行此操作来说,一个尝试并不是一个糟糕的结构。
但是,你必须这样做:
- 从你的黑板上挑一封信。
- 在树中查找当前"word"的节点。 在黑板上选择另一个字母。
- 从步骤2重复,直到:没有找到单词或没有字母在板上。 记住你找到的单词的"分数"。
- 对板上的所有(唯一的?)起始字母重复此过程。
你可能想检查你是否"以前尝试过这个序列",但我不确定这有多大好处。
为了使竞争对手与计算机的竞争更加公平,你可能想要限制计算机的尝试次数,因为在这种情况下,人类可能永远不会战胜计算机。
我想出了一个算法,在整个游戏中执行O(n)操作,其中n是字典的大小。虽然它使用了额外的数据结构,但很可能简单的暴力破解就足够了。如果性能确实是一个问题,请继续阅读。
考虑使用黑板上的字母可以产生的单词集。在整个游戏过程中,单词将从这个集合中移除,因为字母将从棋盘上移除。
可以通过扫描字典来确定单词的初始集合。字母构成黑板上字母子集的单词是有效的。有很多方法可以测试这一点,比如将单词的排序字母与黑板上的排序字母进行比较,或者创建字母频率表并进行比较。
当一个字母被删除时,该字母出现的次数与该字母被删除前在黑板上出现的次数相同的单词必须从集合中删除。例如,如果棋盘上有两个e,其中一个被删除,则只有恰好有两个e的单词需要从集合中删除。
可以使用链表有效地维护单词集。对于常数时间访问得分最高的单词,可以使用O(n)排序算法(如鸽子洞排序)从一开始就对列表进行排序。从列表中删除节点不会打乱顺序。
为了有效地删除具有一定字母频率的所有单词,对链表节点的引用存储在二维数组中。数组的(x, n)条目包含对所有单词恰好n字母x出现的节点的引用。
例如,对包含单词"eye"的节点的引用将存储在数组的('e', 2)和('y', 1)项中。当棋盘上有两个e时,删除一个,则从链表中删除条目('e', 2)中的所有节点。如果一个单词已经被删除,它将被忽略。从链表中移除一个节点是在固定时间内完成的,并且每个单词在整个游戏中最多只能移除一次(并且可能有最多25次额外的移除尝试),使得整个过程O(n)
- 文本文件中的单词链表
- 在指针的帮助下,文本文件中单词的频率
- 如何根据单词在文本中出现的概率输出单词
- 从字符串变量中逐字符读取单词
- C++ 随机生成的字典单词将仅显示以 B 开头的单词
- 如何在没有分隔符的大文本文件中查找所有字典单词
- 使用Trie打印所有字典的单词
- C++ 具有两个类的拼写检查程序;字典和单词
- 找出两个给定单词和字典之间最短的单词阶梯
- 在字典中查找单词模式,高性能
- 给出错误的输出:如何将字符串分解为字典单词
- C 简单字典:排序单词列表
- 我正在尝试制作字典,但我似乎无法搜索以查看该单词是否已经存在
- 过滤掉仅与字典中的单词匹配的排列
- 尝试字典上的数据结构以查找押韵的单词
- 随机选择字典中的单词
- 检查String是否包含字典文件中的单词的快速方法
- 给定一个字符串,在字典中找出它的所有组成单词的排列
- 通过语音在字典中查找单词
- 给定一个字典和字母,找出最长的单词