【问题标题】:whats the fastest string collection structure/algorithm for startswith and/or contains searches什么是startswith和/或包含搜索最快的字符串集合结构/算法
【发布时间】:2013-02-17 23:17:01
【问题描述】:

我有以下情况: 我有一大堆平均长度可能为 30 的字符串(比如说 250.000+)。 我要做的是在这些.. 中进行许多搜索,其中大部分是 StartsWith 和 Contains 类型的。

集合在运行时是静态的。这意味着选择集合的初始读取和填充只进行一次..因此构建数据结构的性能绝对不重要。内存也不是问题:这也意味着如果需要,我不介意在每个集合中有两个具有相同数据的集合(比如一个用于startswith,另一个用于包含)。 唯一重要的是搜索的性能,它应该返回与搜索条件匹配的所有元素。

首先,我遇到了 Trie 或 Radix-tree .. 但也许还有更好的选择?

对于包含 .. 我还没有好主意(除了在列表上运行 linq 查询,它不会很快处理这么多的数据)。

提前谢谢大家!

更新:我忘记了一个重要部分:包含我的意思是在集合中没有完全匹配.. 但我想找到集合中包含给定搜索字符串的所有字符串

【问题讨论】:

  • 包含搜索的子字符串会处理单词还是单个字符?我想知道建立一个索引是否对那个有意义。
  • 应该支持字符。尽管出于性能原因,我可以想象在搜索之前给出至少 3 个或更多字符的长度。 (可以把它想象成文本框中的自动完成功能,只有在输入了一些字符后才会启动)
  • 在网上搜索“Rabin Karp”。这应该可以帮助您入门,因为它链接了多个搜索算法...stoimen.com/blog/2012/04/02/… 还可以考虑使用布隆过滤器并在启动时使用您的字符串预加载它。
  • 感谢您的提示.. 特别是布隆过滤器对我来说是新的。我明天会阅读更多关于这些的内容,现在该睡觉了。
  • 开头。将字符串存储在排序数组中并使用二进制搜索,易于实现、理解和快速。但是对包含没有影响。

标签: c# string algorithm search collections


【解决方案1】:

构建suffix tree 将允许您对O(1) 中的所有字符串并行进行子字符串搜索。我的书呆子不禁注意到它实际上是O(n + m),其中n 是与您的子字符串匹配的字符串数,m 是被查询的子字符串的大小。

那么你问什么是后缀树?在其最基本的实现中,它是一个带有更高级插入方法的 trie:除了添加一个字符串之外,它还将该字符串的每个可能的后缀添加到 trie。在这个数据结构上,子串搜索变成了所有可能后缀的前缀搜索。由于您还想进行前缀搜索,因此您需要在每个插入的字符串和查询子字符串的前面添加一个特殊字符。特殊字符将允许您区分后缀和完整字符串。

虽然后缀树的这种实现非常简单,但效率也很低(O(n^2) 空间和构建时间)。幸运的是,还有其他更有效的实现可以大大减少空间和时间限制。其中之一,Ukkonen 的算法,在this SO answer 中有很好的解释,并将空间限制到O(n)。您可能还想查看suffix arrays,它是后缀树的等效但更有效的表示。

虽然我知道还有更多的后缀树实现(其中一个可能会达到您的用例的最佳位置),但我只是不知道它们。我建议您在确定实施之前对该主题进行一些研究。

【讨论】:

  • 你错了后缀树的低效率。一个好的实现可以改进到 O(n) 或 O(n log n) 时间和 O(n) 空间。 en.wikipedia.org/wiki/Suffix_tree
  • 到目前为止听起来很棒!特别是用特殊字符区分后缀和前缀的想法!
  • 我会阅读更多关于它的信息并确定尝试一下。后缀数组会有缺点吗?如果它们更有效率,那么我可能会立即专注于它们。
  • @nhahtdh 我指的是我在第二段中描述的简单明了的实现。我知道O(n^2) 绑定可以使用更智能的算法得到极大的改进,这就是为什么我在答案中添加了两个替代实现的链接。事实证明,目前对后缀树进行了大量研究,如果您使用维基百科文章中未提及的更高度压缩的变体,您实际上可以击败O(n) 空间限制。
  • @ZeBlob:你应该提到幼稚的实现是不好的。您的帖子可能会引起混淆,即后缀树数据结构总是性能不佳。
猜你喜欢
  • 2011-03-12
  • 1970-01-01
  • 2014-02-18
  • 1970-01-01
  • 2013-08-22
  • 2014-08-27
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
相关资源
最近更新 更多