【问题标题】:String encoding for memory optimization用于内存优化的字符串编码
【发布时间】:2019-11-12 18:07:43
【问题描述】:

我有一个字符串流,格式类似于a:bd:at:wi:r 等。由于我不断附加这些字符串,最后它变成了一个非常大的字符串。

我正在尝试编码,例如:

a:b -> 1
d:a -> 2
etc.

我的意图是使最终的字符串尽可能小以节省内存。因此,我需要为出现最大次数的字符串赋予单个数字值。

我有以下方法:

创建:map<string, int> - 这将保留字符串及其计数。最后,我会将最大计数的字符串替换为 1,然后替换为 2,依此类推,直到地图的最后一个元素。

当前最终字符串的大小约为 100,000 个字符。

我不能在速度上妥协,请建议是否有人有更好的技术来实现这一点。

【问题讨论】:

  • unordered_map 可能会提供更好的性能。但像往常一样,唯一真正的答案是尝试不同的技术并计时。任何人都有太多变数,无法给出明确的建议。这是你必须解决的问题。
  • 字符串 "a:b" 的长度为 4(如果存储为 C 字符串)。将其映射到int(也可能是 4 个字节)不会带来任何优化。实际上,您仍然用 4 个字节加上地图的附加管理数据来表示一个字符串。
  • 必须是可读的字符串吗?否则,您可以使用 char 数组或 struct 数组。
  • 如果你只有 [a-z]:[a-z],可能的字符串的 nr 是 26^2=676 个不同的元素。因此,您可以按字典顺序对字符对进行排序,然后将它们放入具有 676 个元素的 vector 中。例如。 vec[0] 计算“a:a”的 nr,vec[675] 计算“z:z”的 nr。
  • @Scheff 我将使用 ASCII 字符“1”。不是整数,最后我只需要将其保留为紧凑的字符串。

标签: c++ string c++11 optimization


【解决方案1】:

如果我理解正确,您的输入字符串的范围是“a:a”...“z:z”,您只需计算流中每个字符串的出现次数,而不管顺序如何。如果您的分布足够均匀,您可以使用 uint16_t 计算它们。 映射是使用树实现的,因此数组在内存和时间上都比映射更有效。 所以你可以定义一个数组

array<array<uint16_t, 26>, 26> counters = {{}};

假设您的输入是,例如input = "c:d",您可以按如下方式填充数组

    counters[input[0]-'a'][input[2]-'a']++;

最后你可以像这样打印出输入的频率

for (auto i=0; i < counters.size() ; ++i) {
  for (auto j=0; j < counters[i].size(); ++j) {
    cout<<char(i+'a')<<":"<<char(j+'a')<<" "<<counters[i][j]<<endl;
  }
}

【讨论】:

    猜你喜欢
    • 2013-05-14
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-28
    • 2013-08-12
    • 2016-09-01
    相关资源
    最近更新 更多