是否有一个函数是std :: search什么std :: count是std :: find?

时间:2013-05-09 15:09:29

标签: c++ stl

如果标题听起来很奇怪,这是另一种解释:

如果我有 a 的范围,并且我想计算 a 范围内出现的另一个范围 b 的次数,是否有std::有功能吗?

如果不是,有没有一种简单的方法(我可以使用std::search手动循环 - 我说的是更优雅的东西)?

4 个答案:

答案 0 :(得分:3)

我认为你需要建立自己的。以下是我作为实现的想法。

template <typename Iterator1, typename Iterator2>
size_t subsequence_count(Iterator1 haystack_begin, Iterator1 haystack_end, Iterator2 needle_begin, Iterator2 needle_end) {
    size_t count = 0;
    while (true) {
        haystack_begin = std::search(haystack_begin, haystack_end, needle_begin, needle_end);
        if (haystack_begin == haystack_end)
            return count;
        count++;
        haystack_begin++;
    }
}

template <typename Iterator1, typename Iterator2, typename BinaryPredicate>
size_t subsequence_count(Iterator1 haystack_begin, Iterator1 haystack_end, Iterator2 needle_begin, Iterator2 needle_end, BinaryPredicate predicate) {
    size_t count = 0;
    while (true) {
        haystack_begin = std::search(haystack_begin, haystack_end, needle_begin, needle_end, predicate);
        if (haystack_begin == haystack_end)
            return count;
        count++;
        haystack_begin++;
    }
}

使用此代码的一些代码:

int main() {
    std::vector<int> haystack = {1, 19, 7, 23, 2, 19, 19, 19, 19};
    std::vector<int> needle   = {19, 19};

    assert(subsequence_count(begin(haystack), end(haystack), begin(needle), end(needle) == 3);
}

答案 1 :(得分:1)

你可以在范围A上使用std::count_if,在范围B上使用std :: find的lambda。

编辑:用std :: find替换std :: search。

答案 2 :(得分:1)

如果您希望比O(nm)更有效地执行此操作,对于要搜索的字符串中的m个字符n,您可以考虑使用后缀树即可。本质上,这意味着您构建了一个专门的树结构,同时描述了字符串的所有可能后缀。因此,如果你的字符串是“ratatat”,你的后缀字符串将同时代表“ratatat”,“atatat”,“tatat”,“atat”,“tat”,“at”和“t”。因此,一旦构建了树,就可以非常快速地找到(并计算)特定字符串的所有出现。当然,构建它需要一些编程工作和一些内存!

有一个非常好的描述here(这是指Skiena的书The Algorithm Design Manual,这是我读到的书。)

PS我开始寻找后缀树C ++实现。关于这个问题有几个有用的stackoverflow问题,但到目前为止我没有说明什么。

编辑以添加替代算法

第二个想法,我认为Boyer-Moore字符串匹配可能是一个更好的解决方案,尤其是因为有一个boost implementation随时可用 - 而你所说的你要做的就是找到特定的搜索字符串(如果要计算不同搜索字符串的出现次数,则后缀树很好)。基本上b-m算法所做的是利用搜索字符串中的结构在不匹配时向前跳,使用预先计算的表作为搜索字符串(c.f.后缀树预处理要搜索的字符串)。所以你应该能够手动循环使用boyer-moore boost搜索(而不是使用std搜索)并获得显着的效率提升。

答案 3 :(得分:0)

如有疑问,请使用提升:)

#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/foreach.hpp>

using namespace std;
using namespace boost;
using boost::algorithm::find_all;

int main(int argc, char* argv[])
{
    std::vector<double>  haystack{11.0,22.0,33.0,22.0,33.0,44.0,22.0,33.0,22.0};
    std::vector<double> needle{22.0,33.0};

    std::vector<boost::iterator_range<std::vector<double>::iterator>> out;
    boost::algorithm::find_all(out, haystack, needle);

    cout << "matches=" << out.size() << endl;
    cout << endl;

}

基于作为find_all中的bug示例发布的代码 - 在对问题的评论中链接。