使用C ++在另一个字符串中找到给定起始位置和结束位置的子字符串的更快方法?

时间:2017-09-11 16:07:32

标签: c++ string

任务是在给定“haystack”的起始位置和结束位置的另一个字符串(haystack)中找到子字符串(needle)。开始和结束位置遵循STL约定,即结束位置是感兴趣范围之后的字符位置。

例如:使用beg_pos=0查找“567”,“0123456789”中的end_pos=8应返回5,而使用beg_pos=0和{{1}查找“567” }“0123456789”应返回end_pos=4

我可以想象两个简单的实现:

  • 方法1 :使用-1获取子字符串位置,然后将返回值size_t pos = haystack.find(needle, beg_pos);pos进行比较(如果找到)。在最坏的情况下,end_pos函数将一直运行到字符串find的末尾,但haystack之后的搜索是不必要的。如果end_pos很长,性能可能会很差。
  • 方法2 :使用haystack查找位置,然后返回size_t pos = haystack.substr(beg_pos, end_pos-beg_pos).find(needle);(如果找到)。此方法避免了pos+beg_pos之后不必要的搜索问题,但它需要分配一个新的临时字符串,这可能也存在性能问题。

我想知道是否有更快的方法来完成任务。

2 个答案:

答案 0 :(得分:1)

在C ++ 17中,我们有std::string_view,它可以用指针和大小构造。这将允许您获取字符串的只读片段,其中不会复制任何内容。然后,您可以使用std::string_view::find来查找该切片中是否存在子字符串。那看起来像是

std::string haystack = "lots of stuff";
std::string needle = "something";
std::string_view slice(haystack.c_str() + start, end - start); // use end - start to get size of the slice
auto pos = slice.find(needle);
if (pos == std::string::npos)
    return -1;
else
    return pos; // or pos + start if you need the index from the start and not just in the slice.

答案 1 :(得分:0)

前C ++ 17

这是一种我认为最快的方法。它使用std::search,在我看来它是一个基于迭代器的substr。

在此示例中,针的位置相对于haystack的开头而不是被搜索的子字符串返回:

#include <string>
#include <iostream>
#include <algorithm>

int main()
{
    using namespace std::literals;

    auto my_haystack = "0123456789"s;

    auto needle = "567"s;
    auto find_needle = [&needle](auto first, auto last)
    {
        auto i = std::search(first, last, begin(needle), end(needle));
        if (i == last)
            return std::string::npos;
        else
            return std::string::size_type(std::distance(first, i));
    };

    auto in_substring = [](auto&& str, auto b, auto e, auto&& f) -> std::string::size_type
    {
        using std::begin;
        auto brange = begin(str) + b;
        auto erange = begin(str) + e;
        auto p = f(brange, erange);
        if (p != std::string::npos)
            p += b;
        return p;
    };

    auto pos = in_substring(my_haystack, 0, 4, find_needle);
    std::cout << pos << std::endl;

    pos = in_substring(my_haystack, 0, my_haystack.size(), find_needle);
    std::cout << pos << std::endl;

    pos = in_substring(my_haystack, 1, my_haystack.size(), find_needle);
    std::cout << pos << std::endl;

    pos = in_substring(my_haystack, 1, 4, find_needle);
    std::cout << pos << std::endl;
}

示例输出(64位size_type):

18446744073709551615
5
5
18446744073709551615