Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::set如何比std::map慢?_C++_Performance_Visual C++_Map_Set - Fatal编程技术网

C++ std::set如何比std::map慢?

C++ std::set如何比std::map慢?,c++,performance,visual-c++,map,set,C++,Performance,Visual C++,Map,Set,我试图解决这个问题,它基本上希望我输出给定字符串的不同子字符串的数量(最大长度5000) 我将要提出的解决方案效率极低,并且在限制条件下注定要超过时限。然而,这两种解决方案的唯一不同之处(至少就我所能看到/理解的而言)是一个使用std::map,而另一个使用std::set(请参见最后一个for循环的开头。其余的都是相同的,您可以通过任何diff工具进行检查)。map解决方案导致“超出测试3的时间限制”,而set解决方案导致“超出测试2的时间限制”,这意味着测试2使得map解决方案在其上的工作速

我试图解决这个问题,它基本上希望我输出给定字符串的不同子字符串的数量(最大长度5000)

我将要提出的解决方案效率极低,并且在限制条件下注定要超过时限。然而,这两种解决方案的唯一不同之处(至少就我所能看到/理解的而言)是一个使用
std::map
,而另一个使用
std::set
(请参见最后一个for循环的开头。其余的都是相同的,您可以通过任何diff工具进行检查)。map解决方案导致“超出测试3的时间限制”,而set解决方案导致“超出测试2的时间限制”,这意味着测试2使得map解决方案在其上的工作速度比set解决方案快。如果我选择Microsoft Visual Studio 2010编译器,情况就是这样。如果我选择GCC,那么这两种解决方案都会在测试3中产生TLE

我不是在问如何有效地解决这个问题。我在问什么 如何解释使用
std::map
显然比使用
std::set
更有效。我只是看不到这种现象的机制,希望有人能有任何见解

代码1(使用map,TLE 3):

#包括
#包括
#包括
#包括
使用名称空间std;
int main()
{
字符串s;
cin>>s;
向量p;
p、 推回(1);
对于(int i=1;i对于(inti=1;i在这种情况下,我想一个集合只比一个映射快一点。但我认为你不应该假设太多的TLE 2或TLE 3并不是什么大问题。如果你在给定提交时,测试2的同一个解决方案时间限制,而下次它在测试3的时间限制,这可能会发生。我有一些解决方案p在时间限制内完成测试,我敢打赌如果我重新提交测试,他们会失败


我使用Ukonen-Sufix树解决了这个特殊问题。

这取决于所使用的实现算法。通常,集合仅使用关键字段的映射来实现。在这种情况下,使用集合而不是映射会有很小的开销。

我看到的实际差异(如果我遗漏了什么,请告诉我)你是在地图箱里吗

hash_ans[key] = true;
hash_ans.insert(key);
而在设定的情况下,你是这样做的

hash_ans[key] = true;
hash_ans.insert(key);

在这两种情况下,插入一个元素,除非它已经存在,否则它不做任何事情。在这两种情况下,查找都需要找到相应的元素并将其插入失败。在有效的每个实现中,容器将使用树,使得查找同样昂贵。C++标准实际上要求set::insert()

map::operator[]()
的复杂度为O(logn),因此两种实现的复杂度应该相同

现在,一个性能更好的原因是什么?一个区别是,在一种情况下,基础树的节点包含一个
字符串
,而在另一种情况下,它是一个
。由于对包含一个字符串,它必须更大,并对机器的RAM接口施加更大的压力,因此这不能解释加速。它可以做的是扩大节点大小,以便将其他节点推离缓存线,这可能对多核系统的性能不利

总之,我想尝试以下几点:

  • 在集合中使用相同的数据
    我会使用
    struct data:string{bool b};
    来实现这一点,也就是说,将字符串绑定到一个结构中,该结构应该具有与映射元素类似的二进制布局。作为比较器,请使用
    less
    ,以便只有字符串实际参与比较

  • 在地图上使用insert()
    我不认为这是一个问题,但是插入可能会引起一个论点的副本,即使最后没有插入。我希望不会,所以我不太相信这会改变任何事情

  • 关闭调试
    大多数实现都有一个诊断模式,其中迭代器被验证了。您可以使用它来捕获错误,其中C++只说“未定义的行为”,耸肩耸肩和崩溃。这种模式通常不满足复杂性保证,并且总是有一些开销。

  • 阅读代码
    如果set和map的实现具有不同的质量和优化级别,这就可以解释它们之间的差异。尽管如此,我还是希望map和set都构建在同一类型的树上,所以这里也没有太多希望


  • 你自己试过什么吗,比如自己测量时间?甚至是分析?@Plasmah:我相信我已经给出了足够的证据,证明一个比另一个慢。我对这是怎么回事感兴趣possible@PlasmaHH当前位置我认为这是一个非常充分的问题。@ArmenTsirunyan:除此之外,我不认为时间限制超过了我来自某个黑匣子的消息,你不知道它们是如何限制时间的,它有多准确,以及其他什么因素会影响它是比较不同程序速度的一个好方法,分析这两个程序将更准确地告诉你这两个程序在速度上的差异,并且很可能会告诉你足够多的信息,让你了解自己是如何做到的可能,或者让其他人通过更详细地了解时间花在哪里来解释这是怎么可能的。这就是问题所在。