如果标题听起来很奇怪,这是另一种解释:
如果我有 a 的范围,并且我想计算 a 范围内出现的另一个范围 b 的次数,是否有std::
有功能吗?
如果不是,有没有一种简单的方法(我可以使用std::search
手动循环 - 我说的是更优雅的东西)?
答案 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示例发布的代码 - 在对问题的评论中链接。