对于我正在制作的构词游戏,我有一个trie,可以存储字典中的所有可能的单词。目前大约有179,000人。
游戏的工作方式,有5x5(或未来可能更大,取决于这个问题的解决方案效率有多大)字母网格。玩家和PC轮流从这些字母中制作单词,根据单词的字母和长度得到分数(字母估值类似于拼字游戏,但这并不重要)。每当玩家说出一个单词时,这些字母就会从棋盘中删除,并且这种情况一直持续到没有任何单词可以制作,此时网格被重置(并且该轮的获胜者获得奖励)。
问题是这样的:给定一个5x5的字母网格和字典trie,我怎样才能有效地确定可以制作的最长单词或所有可能单词的列表?请注意,字母不需要相互接触即可使用;任何网格的字母都没问题。
我能想到的唯一方法就是在trie上基本上做一个BFS,当下一个字母不在网格中时修剪它,但这对我来说似乎不是很有效,因为它必须要尝试对于网格中的每个字母。有更好的方法吗?
答案 0 :(得分:0)
查找“最佳”单词总是需要在trie中进行一些搜索。但是这样做并不是一个糟糕的结构。
但是,您必须执行以下操作:
你可能想检查一下你之前是否“尝试过此序列”,但我不确定这有多大好处。
为了使竞争对手与计算机竞争合理公平,您可能希望限制计算机的尝试次数,这仅仅是因为在这种情况下人类可能永远不会赢得计算机。
答案 1 :(得分:0)
我想出了一种在整个游戏中执行 O(n)操作的算法,其中 n 是字典的大小。它使用了额外的数据结构,并且很可能简单的暴力就足够了。如果性能确实成为一个问题,请继续阅读。
考虑使用棋盘上的字母可以产生的一组单词。随着信件从董事会中删除,整个游戏中的单词将被删除。
可以通过扫描字典来确定初始单词集。字母组成板上字母子集的单词是有效的。有许多方法可以对此进行测试,例如将单词的排序字母与电路板的排序字母进行比较,或者创建字母频率表并进行比较。
当删除一封信时,必须从该套中移除该字母出现的字数与在该字母移除之前在该字母上所执行的次数相同的字数。例如,如果电路板有两个 e 并且一个被删除,则只需要从集合中删除只有两个 e 的字。
可以使用链表有效维护单词集。对于具有最高分数的单词的恒定时间访问,可以使用 O(n)排序算法(例如pigeonhole sort)在开始时对列表进行排序。从列表中删除节点不会干扰订单。
为了有效删除具有特定字母频率的所有单词,对链表的节点的引用存储在二维数组中。数组的条目(x,n)包含对其单词具有 n 出现的字母 x 的所有节点的引用。
例如,对包含单词“eye”的节点的引用将存储在条目('e',2)和('y'中,1)的数组。当电路板上有两个 e 并且一个被移除时,条目('e',2)中的所有节点都将从链接列表中删除。如果某个单词已被删除,则会被忽略。
从链接列表中删除节点是在恒定时间内完成的,并且每个单词在整个游戏中最多可以删除一次(并且可能最多有25次删除尝试),使整个过程 O( n)的