有什么办法可靠地压缩短串?

时间:2012-11-20 20:54:57

标签: javascript string encoding compression query-string

我有一个长度恰好为53个字符的字符串,其中包含一组有限的可能字符。

[A-Za-z0-9\.\-~_+]{53}

我需要将其减少到50而不会丢失信息并使用相同的字符集。

我认为应该可以将大多数字符串压缩到50长度,但是对于所有可能长度为53的字符串是否可能?我们知道在最坏的情况下,可能的集合中的14个字符将被使用。我们可以使用这些信息吗?

感谢阅读。

5 个答案:

答案 0 :(得分:11)

如果如你所说的那样,你的输出字符串必须使用与输入字符串相同的字符集,如果你对输入字符串的要求一无所知,那么不,压缩是不可能的每个可能的53个字符的字符串,最多50个字符。这是pigeonhole principle的简单应用。

  • 您的输入字符串可以表示为base 67中的53位数字,即0到67之间的整数 53 - 1≅6* 10 96 < / SUP>
  • 您希望将这些数字映射到0到67之间的整数 50 - 1≅2* 10 91
  • 因此,通过鸽子原则,您可以保证67 3 = 300,763个不同的输入将映射到每个可能的输出 - 这意味着,当您去解压缩时,您无法知道你应该将300,763张原件中的哪一张映射回来。

要完成这项工作,您必须更改您的要求。您可以使用更大的字符集对输出进行编码(如果每个字符有87个可能的值,则可以将其缩小到50个字符,而不是输入中的67个字符)。或者你可以识别输入中的冗余 - 也许第一个字符只能是'3'或'5',第十九和第二十个是一个州名缩写,它只能有62种不同的可能值,就是那种东西。 / p>

如果你不能做这些事情中的任何一个,你将不得不使用压缩算法,如霍夫曼编码,并接受一些字符串将是可压缩的(并且变短)而其他字符串不会(并且将会更长)。

答案 1 :(得分:5)

一个字节(字符)可以编码256个值(0-255),但是你的有效字符集只使用67个值,可以用7位表示(唉,6位只能得到64个)而且你的字符都没有使用字节的高位。

鉴于此,您可以丢弃高位并仅存储7位,将下一个字符的初始位运行到第一个字符的“备用”空间。这将只需要47个字节的空间来存储。 (53 x 7 = 371位,371/8 = 46.4 == 47)

这不是真正的压缩,而是编码的更改。

例如“ABC”是0x41 0x42 0x43

     0x41        0x42        0x43  // hex values
0100 0001   0100 0010   0100 0011  // binary
 100 0001    100 0010    100 0011  // drop high bit
// run it all together
100000110000101000011
// split as 8 bits (and pad to 8)
10000011   00001010   00011[000]
    0x83       0x0A        0x18

作为一个例子,这3个字符不会节省任何空间,但是你的53个字符总是以47保证。

但请注意,如果这对您来说很重要,那么输出将不会出现在原始字符集中。

该过程变为:

original-text --> encode --> store output-text (in database?)
retrieve --> decode --> original-text restored

答案 2 :(得分:4)

在最一般的情况下,你所要求的是不可能的,这可以非常简单地证明。

假设可以在同一组中将任意53个字符串编码为50个字符。这样做,然后在编码的字符串中添加三个随机字符。然后你有另一个任意的53个字符串。你怎么压缩它?

因此无法保证您想要的任何可能的数据。但是,您的所有真实数据都可能具有足够低的熵,您可以设计一个可行的方案。

在这种情况下,您可能希望做一些霍夫曼编码的变体,它基本上为您集合中的字符分配可变位长度编码,使用最常用字符的最短编码。您可以分析所有数据以提出一组编码。在Huffman编码之后,您的字符串将是一个(希望更短)的比特流,您可以将其编码为每个字符6位的字符集。它可能足够短,可用于所有真实数据。

像Smaz这样的基于库的编码(在另一个答案中引用)也可以起作用。同样,不可能保证它适用于所有可能的数据。

答案 3 :(得分:3)

如果我没记错的话,Huffman coding将成为存储数据最紧凑的方式。自从我用它来快速编写算法以来已经太久了,但总体思路已被涵盖here,但如果我没记错的话,你会做的是:

  1. 获取所使用的每个字符的计数
  2. 根据发生的频率对其进行优先排序
  3. 根据优先级构建树
  4. 通过遍历树获取每个字符的压缩位表示(从根开始,left = 0 right = 1)
  5. 用树中的位替换每个字符

答案 4 :(得分:2)

Smaz是一个简单的压缩库,适合压缩非常短的字符串。