在c ++ 11

时间:2016-08-01 16:28:55

标签: string c++11 dictionary svm sparse-matrix

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

一种解决方案:将字符串累积为std::unordered_map<string,int>;然后迭代地图,从递增计数器分配int。然后查找,unordered_map::find("foo")->second。但它闻起来像其他容器会更快,开销更少(内置索引,而不是手工编码)。也许unordered_set和指针算术??

范围限制似乎使得完美的哈希变得困难。

(int&#39; s范围受到限制,因为它索引到传递给svm_light的特征向量。该软件不使用稀疏存储,因此具有数万亿(通常为零)元素的向量使它耗尽内存。所以这个字符串到int的预处理类实现了一个稀疏的数据结构。)

3 个答案:

答案 0 :(得分:2)

您所描述的内容如perfect hashing

有些C ++库可以实现完美的哈希,例如Tiny perfect hash library for C, C++, and Lua

答案 1 :(得分:1)

将字符串转换为int64_t,将它们存储在unordered_set中,并将迭代器用作唯一索引。 实际上,您将实现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;

输出:

1
2
3

现在您已拥有唯一的映射,请使用unordered_map来实现目标,并放弃unordered_set

  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;

查找将是O(1)。

答案 2 :(得分:0)

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

作为基数排序的替代方法,您可以简单地将字符串视为uint64_t并使用std::sort(它实现了经过优化的内部排序,尽管时间更长,但它可以执行与约束相同的基数复杂性)。

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

[edit]为了将字符串放入unordered_map,你可能想要实现自己的散列算法,我建议使用 djb2 ,它具有良好的统计特性并且易于实现。