【问题标题】:C++: find a string in an array of sub-string efficiently [duplicate]C ++:有效地在子字符串数组中查找字符串[重复]
【发布时间】:2017-01-14 06:08:53
【问题描述】:

我有一个字符串前缀数组:std::vector<std::string> haystack = {"/bin/", "/usr/bin/", "/usr/local/bin/"}

有没有一种有效的方法可以使用标准 C++ 库找到 std::string needle = "/bin/echo" 以来自 haystack 的子字符串开头?

如果我需要找到完全匹配,我可以使用std::set<std::string>,这将执行高效的二进制搜索,但是我只需要匹配字符串的第一部分,所以目前我正在使用简单循环:

for (auto it = haystack.begin(); it != haystack.end(); it++) {
    if (needle.compare(0, it->size(), *it) == 0) {
        return true; // Found it
    }
}
return false;

【问题讨论】:

  • 请定义高效。要缩短代码,请使用std::find_if()
  • 比遍历整个haystack 数组(即O(n))更快。 find_if 将以 O(n) 的速度执行完全相同的循环。
  • 分而治之。但即使这样也不能保证比 O(n) 更快。
  • 对搜索字符串和搜索文本更精确。你想测试每个字符串的任何前缀。是否所有前缀都是以 / 结尾的目录。您想在前缀目录下的任何级别查找文件还是只查找直接子目录。这种细节将有助于找到最有效的方法。它还取决于数据大小...
  • 前缀是否排序? “前缀”是什么意思:完全匹配还是部分匹配? “/bin/foo/echo”会匹配“/bin/”吗?前缀可以包含“/usr/lib”之类的内容并匹配“/usr/lib64/baz”吗?

标签: c++ arrays string stl


【解决方案1】:
  1. 按字符串长度降序排列hasystack
  2. 按顺序比较不超过needle的前缀;从右到左做。例如。如果 prefix 的长度为 5 个字符,则将 prefix[4]needle[4] 进行比较,然后将 prefix[3]needle[3] 进行比较,依此类推。

这样您将立即丢弃许多不匹配的内容。作为奖励,您将首先找到最长的匹配项(可能正是您想要的)。

【讨论】:

  • 为什么要对大海捞针?这会将其变成大海捞针大小的O(n log n) 操作。否则为O(n)
  • @Richard:这不是绝对必要的。假设不需要首先找到最长的匹配项,根据具体情况,排序可能有用也可能没有用。
【解决方案2】:

我要添加的一个“优化”是,如果您使用std::any_of,它将在找到第一个子字符串匹配时短路

auto found = std::any_of(begin(haystack),
                         end(haystack),
                         [&needle](std::string const& sub)
                         { 
                             return needle.compare(0, sub.size(), sub) == 0;
                         });

否则如果你想找到匹配的哪个子字符串,你可以使用std::find_if,它也会在找到第一个匹配时短路。

auto match = std::find_if(begin(haystack),
                          end(haystack),
                          [&needle](std::string const& sub)
                          { 
                              return needle.compare(0, sub.size(), sub) == 0;
                          });

【讨论】:

  • 我只需要在数组中找到第一个匹配项,我已经更新了我的代码示例。
猜你喜欢
  • 2019-07-16
  • 2014-10-31
  • 1970-01-01
  • 1970-01-01
  • 2014-05-09
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
  • 2015-03-27
相关资源
最近更新 更多