【问题标题】:Forward-Only Seeking Lookup Algorithm前向查找算法
【发布时间】:2019-12-24 16:40:59
【问题描述】:

给定一个格式为{Length}.{Text}(如3.foo)的字符串,我想从有限列表中确定给定字符串是哪个字符串。 阅读器从 0 索引开始,可以向前搜索(如果需要,可以跳过字符)。

例如,考虑以下列表:

10.disconnect
7.dispose
7.distort

确定已显示哪些字符串的最短方法可能如下所示:

if (reader.Current == "1")
{
  // the word is "disconnect"
}
else
{
  reader.MoveForward(5);
  if (reader.Current == "p")
  {
    // the word is "dispose"
  }
  else
  {
    // the word is "distort"
  }
}

这个问题有 2 个部分,但我希望有人能指出我需要阅读更多信息的正确算法或信息论方面。

1) 给定一个有限的字符串列表,生成逻辑的最佳方法是平均需要最少次数的查找和比较来确定呈现的是哪个单词?

2) 与第一个一样,但允许加权以便可以考虑热路径。即,如果“distort”这个词比“disconnect”和“dispose”这个词的可能性高4倍,那么上面显示的逻辑如果结构如下,平均性能会更高:

reader.MoveForward(5);
if (reader.Current == "t")
{
  // the word is distort
}
else //...

注意:我知道示例集中的第 6 个字符是唯一的,因此解决示例集所需要做的就是在该字符上使用 switch,但请假设有更长的列表单词。

另外,这不是家庭作业——我正在为Guacamole protocol 编写解析器/拦截层。我看过二叉树、Tries、Ulam's Game 和其他一些,但没有一个符合我的要求。

【问题讨论】:

  • 是否有可能对给定的列表进行排序/排序?还是需要保持原样。
  • 您可以对列表进行排序。但是,这里的目标是根据从给定列表派生的规则来设计代码(设计代码......?)。希望这是有道理的?我发现如果你删除只进规则,通过检查每个索引处的字符分布来完成这项任务(手动/手动)相当容易;分布越高,该指数越有用。前进只会让它变得更加棘手:-/
  • 你的问题太宽泛了。也就是说,我认为你也找错了树。 1) 还没有人为该协议编写过解析器吗?使用现有艺术可能更有意义。 2) 你真的有性能问题吗?字符串解析不应该给计算机带来太多的任务,如果有的话。 I/O 和其他操作肯定会主导计算成本吗? ...
  • ... 3) “只进”真的是这里重要的目标吗?例如,如果字符串总是采用“.”的形式,并且您可以选择有限的东西,我希望字典更简单、更快。 4) 如果您坚持“仅向前”策略,我认为您正在查看状态机或该主题的一些变体。
  • 如果性能很重要,并且您认为您的测试表明基于字典的方法和显式实现的状态机之间存在显着差异,那么您应该只使用后者。如果您对是否可以改进基于字典的方法感到好奇,可以将其发布到 codereview.stackexchange.com。我不打算再搜索我的帖子了……旧新闻组的存档似乎不完整,而且无论如何挖掘它似乎没有多大意义。

标签: c# algorithm guacamole


【解决方案1】:

我不知道这是否有任何帮助,但无论如何我都会投入我的 5 美分。

如果列表中的字符串越多,树就会自动变得更细化,并且针对“热路径”完成对现有叶子的检查?

例如,我会在您的列表中包含这样的内容:

10.断开连接 7.处置 7.扭曲

root ---- 7 "check 4th letter" ------ if "t" return "distort"
     |      "in the order of "   |
     |      "  hot paths     "    --- if "p"return "dispose"
     |
     ----10 ---- return "disconnect"

您可以动态构建它。例如,如果你添加 7.display 它会是

root ---- 7 "check 4th letter" ------ if "t" return "distort"
     |      "in the order of "   |
     |      "  hot paths     "    --- if "p" --- "check 5th letter" --- if "o" ...
     |                                                               |
     ----10 ---- return "disconnect"                                  --- if "l" ...

因此树中的节点将有一个变量“要检查的索引”,并与可能的结果相对应(顺序由统计确定)。就像这样:

# python example
class node():
  def __init__(which_index, letter):
    self.which_index = which_index # which index this node checks to determine next node
    self.letter = letter # for which letter we go to this node
    self.leaves = SomeLinkedList()

  def add_leaf(node):
    self.leaves.putInCorrectPositionDependingOnHowHotPathItIs(node)

  def get_next(some_string):
    for leaf in self.leaves:
      if some_string[self.which_index] == leaf.letter:
         return leaf
    raise Exception("not found")

另一种选择当然是散列。

但是,如果您进行微优化,则很难说,因为还有其他因素在起作用(例如,您从内存缓存中节省的时间可能非常重要)。

【讨论】:

  • 我知道你打算用这个去哪里,当然这本质上就是我用来表示这个的机制,同时试图暴力解决树应该在什么顺序。我真的after 是一种导出索引/字母/决定的方法。我已经能够手动计算一个仅向前的决策树,它需要我检查最多 3 个字节,通常是 2 个字节。但我必须手动完成,我不知道如何最好地考虑热路径。我怀疑我没有很好地问我的问题...... :)
猜你喜欢
  • 2011-03-16
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
  • 2016-07-16
  • 2011-05-27
相关资源
最近更新 更多