我有一个长度恰好为53个字符的字符串,其中包含一组有限的可能字符。
[A-Za-z0-9\.\-~_+]{53}
我需要将其减少到50而不会丢失信息并使用相同的字符集。
我认为应该可以将大多数字符串压缩到50长度,但是对于所有可能长度为53的字符串是否可能?我们知道在最坏的情况下,可能的集合中的14个字符将被使用。我们可以使用这些信息吗?
感谢阅读。
答案 0 :(得分:11)
如果如你所说的那样,你的输出字符串必须使用与输入字符串相同的字符集,如果你对输入字符串的要求一无所知,那么不,压缩是不可能的每个可能的53个字符的字符串,最多50个字符。这是pigeonhole principle的简单应用。
要完成这项工作,您必须更改您的要求。您可以使用更大的字符集对输出进行编码(如果每个字符有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,但如果我没记错的话,你会做的是:
答案 4 :(得分:2)
Smaz是一个简单的压缩库,适合压缩非常短的字符串。