Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.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
String 将一百万个字符串映射到c++;11_String_C++11_Dictionary_Svm_Sparse Matrix - Fatal编程技术网

String 将一百万个字符串映射到c++;11

String 将一百万个字符串映射到c++;11,string,c++11,dictionary,svm,sparse-matrix,String,C++11,Dictionary,Svm,Sparse Matrix,我有一百万个ASCII字符串,没有重复项,每个最多7字节长。我需要将每个字符串映射到一个正整数。这些INT中最大的应该不会超过一百万。虽然初始化可能很慢,但查找应该很快:给定一个字符串,返回相应的int(如果找不到,则返回-1)。如何在C++11中实现这一点 一种解决方案是:将字符串累积到std::无序_映射中;然后在映射上迭代,从递增计数器分配整数。然后要查找,只需unordered_map::find(“foo”)->second。但它闻起来像其他容器更快,开销更小(内置索引,而不是手工编码

我有一百万个ASCII字符串,没有重复项,每个最多7字节长。我需要将每个字符串映射到一个正整数。这些INT中最大的应该不会超过一百万。虽然初始化可能很慢,但查找应该很快:给定一个字符串,返回相应的int(如果找不到,则返回-1)。如何在C++11中实现这一点

一种解决方案是:将字符串累积到
std::无序_映射中
;然后在映射上迭代,从递增计数器分配整数。然后要查找,只需
unordered_map::find(“foo”)->second
。但它闻起来像其他容器更快,开销更小(内置索引,而不是手工编码)。可能是
无序集
和指针算法

范围限制似乎使完美散列变得困难


(int的范围受到限制,因为它索引到传递给的特征向量中。该软件不使用稀疏存储,因此具有数万亿(大部分为零)元素的向量使其内存不足。因此,这个字符串到int的预处理排序实现了一种稀疏数据结构。)

您描述的内容如下所示


<>有实现完美散列的C++库,例如

如果你有100万个字符串,每个字节长度都是7个字节,那么这是使用基数排序的完美先决条件;基本上,首先将所有10^6字符串存储在一个大数组中(它只有7MB/6.7MB,所以很容易管理),然后使用基数排序算法进行排序-时间复杂度O(wn),w=7,n=10^6在您的情况下,可以在原地实现。实现的细节对于保持低的线性复杂度很重要,但基数排序很容易实现

作为基数排序的替代方法,您可以简单地将字符串视为
uint64\t
,并使用
std::sort
(它实现了经过良好优化的内部排序,尽管时间复杂度更高,但其性能可能与约束的基数一样好)

一旦对数组进行排序,您将对其进行迭代,并将数组的索引放入普通
std::unordered_map
,并将字符串作为键。因此,最终您在基本线性时间内创建了完美的哈希,并以平均O(1)的反向查找结束


[编辑]要将字符串放入无序映射,您可能需要实现自己的哈希算法,我建议使用djb2,它具有良好的统计特性,并且易于实现。

将字符串转换为
int64\t
,将其存储在
无序映射集中
,并使用迭代器作为唯一索引。 实际上,您将实现O(1)查找,加上O(N)计算迭代器偏移量。您还可以保证最大索引不会超过数组的大小

  unordered_set<int> s;
  s.insert(10);
  s.insert(2000000);
  s.insert(5000000);

  int index = std::distance(s.find(10), s.end());
  cout << index << endl;
  index = std::distance(s.find(2000000), s.end());
  cout << index << endl;
  index = std::distance(s.find(5000000), s.end());
  cout << index << endl;
现在您有了一个唯一的映射,使用
无序映射
来实现您的目标,并放弃
无序映射集

  unordered_set<int> s;
  unordered_map<int,int> m;
  s.insert(10);
  s.insert(2000000);
  s.insert(5000000);

  int index = std::distance(s.find(10), s.end());
  m[10] = index;
  cout << index << endl;
  index = std::distance(s.find(2000000), s.end());
  m[2000000] = index;
  cout << index << endl;
  index = std::distance(s.find(5000000), s.end());
  m[5000000] = index;
  cout << index << endl;

  s.clear();
  cout << m[10] << " " << m[2000000] << " " << m[5000000] <<  endl;
无序的集合;
无序地图m;
s、 插入(10);
s、 插入(2000000);
s、 插入(5000000);
int index=std::distance(s.find(10),s.end());
m[10]=指数;

你能举一个这样的映射的例子吗?我遗漏了什么<代码>10^6
字符串,每个不超过7字节,并且没有重复?这不是一个解决方案,但我会将它们放在一个向量中,排序,然后使用二进制搜索。标记,O(n)查找太慢了。Fran,O(logn)更好,但仍然比无序映射的O(1)慢。是的,在这个术语中,我需要一个几乎“最小完美散列函数”。但制作一个是。@CamilleGoudeseune你看过我提供的CHD基本库链接了吗?GNU gperf已经过时了,80%的负载系数太棒了!我主要是想避免低于0.01%:)一个7字节的sting适合一个int64\t,而散列是。。。本身@艾米利奥加拉瓦格利亚嗯。。。
这些int的最大值应该不超过一百万
?有些字符串小于7字节。即便如此,将它们视为64位整数还是很聪明的!如果在查找过程中使用的数据结构是一个
无序的\u映射
,为什么还要事先进行排序呢?这听起来并不比我最初提出的解决方案简单。你问题中的第二句话是:“这些INT中最大的应该不超过一百万”;)好的,我会详细说明-你最初的建议很好,但你是对的-它可能会有太多的开销。我认为,为连续内存区域实现排序比在
std::unordered\u set
的迭代过程中到处跳跃要快。因此,构建映射将比您最初建议的略快一些。我仍然不知道在填充u_映射之前进行排序有什么帮助。u_图存储数据,所以,嗖,再见到参考位置。
  unordered_set<int> s;
  unordered_map<int,int> m;
  s.insert(10);
  s.insert(2000000);
  s.insert(5000000);

  int index = std::distance(s.find(10), s.end());
  m[10] = index;
  cout << index << endl;
  index = std::distance(s.find(2000000), s.end());
  m[2000000] = index;
  cout << index << endl;
  index = std::distance(s.find(5000000), s.end());
  m[5000000] = index;
  cout << index << endl;

  s.clear();
  cout << m[10] << " " << m[2000000] << " " << m[5000000] <<  endl;