【问题标题】:Binary String Search - minimum bin width?二进制字符串搜索 - 最小 bin 宽度?
【发布时间】:2012-12-17 19:59:06
【问题描述】:

我碰巧在 Python 中构建二进制搜索,但这个问题通常与二进制搜索结构有关。

假设我有大约 1000 个符合条件的候选人,我正在使用二分搜索进行搜索,采用经典方法二等分排序的数据集并重复此过程以缩小符合条件的集合以进行迭代。候选人只是名字的字符串,(first-last 格式,例如“Peter Jackson”)我最初按字母顺序对集合进行排序,然后使用类似这样的方法进行二等分:

hi = len(names)
lo = 0
while lo < hi:
  mid = (lo+hi)//2
  midval = names[mid].lower()
  if midval < query.lower():
    lo = mid+1
  elif midval > query.lower():
    hi=mid
  else:
    return midval
return None

这段代码改编自这里:https://stackoverflow.com/a/212413/215608

事情就是这样,上面的过程假设一个完全匹配或根本没有结果。如果查询只是针对“彼得”,但有几个姓氏不同的彼得怎么办?为了归还所有的 Peters,必须确保被平分的“箱子”永远不会变得如此之小,以至于除了符合条件的结果。为了返回所有 Peters,二等分过程必须停止并让与正则表达式/常规旧字符串匹配之类的东西。

我并不是在问如何实现这一点,而是这种类型的搜索被称为...什么是带有“bin 大小”分隔标准的二分搜索?有条件地平分数据集的东西,一旦满足条件,就会回退到其他形式的字符串匹配,以确保查询中可以有效地有一个结束通配符(因此搜索“彼得”将得到“彼得杰克逊”和“彼得爱德华兹”)

希望我已经清楚了我的意思。我意识到在典型的数据库场景中,名称可能是分开的,这只是作为概念证明。

【问题讨论】:

  • 在最坏的情况下可能都是彼得,不是吗?
  • 确实,在最坏的情况下(或者我应该说是预期的情况?)所有的 Peters 都会被取出。
  • 所以看来您必须根据您可能搜索的内容进行分类。我猜你可以做一个二进制直到你找到一个匹配,然后在两个方向上做一个线性搜索来找到所有其他的匹配。不确定我是否称它为 bin,但您可以将数据组织成二叉树,并且是线性的。
  • 我想可以为二进制迭代设置一个硬编码限制,有点像“对数时间到一个点”的方法,然后从那里开始线性化。我只是想知道考虑到上面的简单控制流程,可以采取哪些方法(如果有任何“命名”的方法)。在什么时候它会变成线性的,并且基于什么条件(因为这些条件永远不会真正匹配,也许也可以调用正则表达式?)
  • 认为一旦找到匹配项,您就需要线性化。不知道该怎么称呼这个。我猜你不想制作一个“peter”bin和一个“sally”bin等。不确定正则表达式在哪里会有所帮助。除非这就是你开始搜索的原因,但我认为我没有抓住你的意思。

标签: algorithm search binary-search-tree


【解决方案1】:

这种两段式搜索我没遇到过,不知道有没有名气。但是,我可以提出一种方法来执行它。

假设您已经运行了第一阶段,但没有找到匹配项。

您可以使用一对二分搜索和一个特殊的比较器来执行第二阶段。二进制搜索将使用与bisect_left and bisect_right 相同的原理。您将无法直接使用这些函数,因为您需要一个特殊的比较器,但您可以将它们用作实现的基础。

现在到比较器。在将列表元素x 与搜索键k 进行比较时,比较器将只使用x[:len(k)] 而忽略x 的其余部分。因此,在搜索“Peter”时,列表中的所有 Peter 都会比较等于键。因此,bisect_left()bisect_right() 将为您提供包含列表中所有 Peters 的范围。

所有这些都可以使用O(log n) 比较来完成。

【讨论】:

  • 第一个比较应该仍然只是一个平分,对吧?因此,找到 Peter 的第一个实例(或只是最初的二等分),然后使用比较器仅匹配与查询相关的许多字符...
  • @DeaconDesperado:第一种方法查找完全匹配并最多返回一个,而第二种查找前缀匹配并返回一个范围。您可以根据您的应用程序混合和匹配这些属性...
【解决方案2】:

在您的二分搜索中,您可以找到完全匹配或匹配的区域。
因此,在您的情况下,您需要获取包含Peter 的区域的上限和下限(hilo)并返回所有中间字符串。

但如果你的目标是显示一个单词的下一个单词,你应该查看 Tries 而不是 BST

【讨论】:

  • 谢谢,我想我明白你在说什么...... hi 和 lo 计算必须考虑子集是否完全由良好的匹配组成。我明白你关于“下一个词”的意思......已经为此使用了后缀树。
  • the hi and lo calculation would have to take into account whether or not the subset is entirely made up of good matches 它不必那么复杂,因为元素已经排序。所以你需要的只是low-hi中的所有元素
猜你喜欢
  • 2013-11-13
  • 2021-11-19
  • 1970-01-01
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2022-07-31
相关资源
最近更新 更多