C++ Boggle Solver:在集合中查找前缀
Posted
技术标签:
【中文标题】C++ Boggle Solver:在集合中查找前缀【英文标题】:C++ Boggle Solver: Finding Prefixes in a Set 【发布时间】:2012-01-29 02:53:22 【问题描述】:这是一个家庭作业,所以我不想要确切的代码,但如果有任何想法可以帮助我指明正确的方向,我将不胜感激。
任务是编写一个解谜程序。我觉得递归部分已经记下来了,但我需要一些关于如何将当前字符序列与字典进行比较的见解。
我需要将字典存储在集合或排序列表中。我一直在尝试一种使用集合来实现这一点的方法。为了让程序运行得更快而不是走死胡同,我需要检查当前字符序列是否作为集合(字典)中任何内容的前缀存在。
我发现 set.find() 操作仅在字符串完全匹配时才返回 true。在实验室要求中,教授提到:
"如果字典存储在一个集合中,许多数据结构库都提供了一种方法来查找集合中最接近您正在搜索的字符串。这样的操作可以用来快速找到一个单词给定的前缀。”
我今天一直在寻找教授所描述的内容。我找到了很多关于尝试的信息,但由于我需要使用列表或集合,我认为这不会起作用。
我也尝试查找自动完成函数的算法,但我发现的算法对于我在这里要完成的任务来说似乎非常复杂。
我还考虑使用 strncmp() 将当前序列与字典集中的单词进行比较,但同样,我不知道在这种情况下它究竟会如何发挥作用,如果有的话。
是否值得继续研究这将如何在集合中工作,或者我应该尝试使用排序列表来存储我的字典?
谢谢
【问题讨论】:
【参考方案1】:正如@Raymond Hettinger 在他的回答中提到的那样,trie 在这里非常有用。但是,如果您不喜欢编写 trie 或者更喜欢使用现成的组件,您可以使用单词按字母顺序排列的可爱属性来检查给定前缀是否存在的 O(log n) 时间。这个想法如下 - 例如,假设您正在检查前缀“thr”。如果您注意到,以前缀“thr”开头的每个单词都必须夹在字符串“thr”和“ths”之间。例如,thr ≤ through
由于您使用的是 C++,因此您可以使用 std::vector
和 std::lower_bound
算法。您也可以将所有单词放入std::set
并使用set
的lower_bound
版本。例如:
std::set<std::string> dictionary;
std::string prefix = /* ... */
/* Get the next prefix. */
std::string nextPrefix = prefix;
nextPrefix[nextPrefix.length() - 1]++;
/* Check whether there is something with the prefix. */
if (dictionary.lower_bound(prefix) != dictionary.lower_bound(nextPrefix))
/* ... something has that prefix ... */
else
/* ... no word has that prefix ... */
也就是说,trie 在这里可能是一个更好的结构。如果您有兴趣,还有另一种称为 DAWG (Directed Acyclic Word Graph) 的数据结构,它与 trie 相似,但使用的内存要少得多;在斯坦福的 CS 入门课程(其中 Boggle 是一项作业)中,实际上为学生提供了一个包含该语言中所有单词的 DAWG。还有另一种称为ternary search tree 的数据结构,它位于二叉搜索树和特里树之间,如果您想研究一下,这里可能会有用。
希望这会有所帮助!
【讨论】:
感谢 Raymond Hettinger 和 templatetypedef。我认为如果这项任务允许,trie 将是最好的选择。我会看看lower_bound。【参考方案2】:trie 是解决这个问题的首选数据结构。
如果您仅限于集合和字典,我会选择一个将前缀映射到可能匹配数组的字典:
asp -> aspberger aspire
bal -> balloon balance bale baleen ...
【讨论】:
我不确定我是否同意映射到前缀是正确的调用;这是非常低效的内存。 @templatetypedef 鉴于您只允许使用集合或排序列表,因此选项有些受限。 RightCall™ 将使用 trie。以上是关于C++ Boggle Solver:在集合中查找前缀的主要内容,如果未能解决你的问题,请参考以下文章
如何从字母矩阵中找到可能的单词列表 [Boggle Solver]