Un algorithme de compression efficace pour les chaînes de texte courtes [fermé]


126

Je recherche un algorithme pour compresser de petites chaînes de texte: 50-1000 octets (c'est-à-dire des URL). Quel algorithme fonctionne le mieux pour cela?


1
Où souhaitez-vous utiliser ces chaînes compressées?
Gumbo

1
Est-ce que cela va vers tinyurlsou quelque chose à voir avec l'espace de stockage?
nik

6
Je suis intéressé par un algorithme pour compresser les URL, le meilleur taux de compression est plus important que le coût de fonctionnement. Pas intéressé par les services en ligne comme tinyurls ou tr.im. Je recherche un algorithme pas un service. Ne pensez pas que d'autres informations pourraient être utiles ...
Vasily Korolev

3
@Gumbo: "Les algorithmes de compression de texte pour les chaînes courtes" suffisent pour trouver des algos, pourquoi êtes-vous si intéressé à savoir à quoi ils servent? Je suis sûr que l'OP pourra trouver celui qui fait ce qu'il veut.
Dervin Thunk

7
@Vasily, un petit indice: chaque fois que vous posez une question sur SO sous la forme de "Quel est le meilleur XYZ?", Votre question est presque obligée de recevoir des votes pour la clôture, car demander le meilleur peut conduire à un produit inutile des comparaisons, ou dans le pire des cas, même des guerres de flammes. (Il suffit généralement d'un très petit changement pour éviter cela: si vous posez la même question comme "Veuillez suggérer un XYZ.", Vous n'obtiendrez pas autant de votes de clôture, même si c'est fondamentalement la même question!)
stakx - ne contribuant plus le

Réponses:


62

Découvrez Smaz :

Smaz est une bibliothèque de compression simple adaptée à la compression de chaînes très courtes.


17
Voir github.com/antirez/smaz/blob/master/smaz.c - il s'agit d'une variante de codage, pas de compression en soi (du moins pas entièrement). Il utilise un dictionnaire statique de mots et de lettres.
Roy Tinker

7
Remarque: il s'agit du projet d'antirez. Il est l'un des principaux auteurs de Redis et a la très bonne réputation de publier un code de production de haute qualité.
Homer6

7
L'algorithme smaz est optimisé pour les textes anglais et ne fonctionne donc pas bien pour les chaînes aléatoires. Voici quelques exemples ( string:orig_size:compr_size:space_savings): This is the very end of it.:27:13:52%, Lorem ipsum dolor sit amet:26:19:27%, Llanfairpwllgwyngyll:20:17:15%, aaaaaaaaaaaaa:13:13:0%, 2BTWm6WcK9AqTU:14:20:-43%,XXX:3:5:-67%
mykhal

4
Jetez également un œil à une compression plus faible mais un algorithme rapide shoco ed-von-schleck.github.io/shoco
Dickey Singh

Ajoutez ma bibliothèque Unishox à la liste github.com/siara-cc/unishox . Il fonctionne mieux que Smaz et Shoco et prend en charge la compression des chaînes UTF-8.
arun

28

Huffman a un coût statique, la table Huffman, donc je ne suis pas d'accord que ce soit un bon choix.

Il existe des versions adaptatives qui éliminent cela, mais le taux de compression peut en souffrir. En fait, la question que vous devriez vous poser est "quel algorithme pour compresser les chaînes de texte avec ces caractéristiques". Par exemple, si de longues répétitions sont attendues, un simple encodage Run-Lengh pourrait suffire. Si vous pouvez garantir que seuls les mots anglais, les espaces, la ponctuation et les chiffres occasionnels seront présents, alors Huffman avec une table de Huffman prédéfinie pourrait donner de bons résultats.

En règle générale, les algorithmes de la famille Lempel-Ziv ont une très bonne compression et de très bonnes performances, et leurs bibliothèques abondent. J'irais avec ça.

Avec l'information que ce qui est compressé sont des URL, alors je suggérerais qu'avant de compresser (avec n'importe quel algorithme facilement disponible), vous les CODIFIEZ. Les URL suivent des modèles bien définis, et certaines parties sont hautement prévisibles. En utilisant ces connaissances, vous pouvez codifier les URL en quelque chose de plus petit pour commencer, et les idées derrière l'encodage Huffman peuvent vous aider ici.

Par exemple, en traduisant l'URL en un flux binaire, vous pouvez remplacer "http" par le bit 1, et tout le reste par le bit "0" suivi du véritable procotol (ou utiliser une table pour obtenir d'autres protocoles courants, comme https, ftp, fichier). Le ": //" peut être complètement supprimé, tant que vous pouvez marquer la fin du protocole. Etc. Allez lire sur le format des URL et réfléchissez à la façon dont ils peuvent être codifiés pour prendre moins de place.


4
Pas si la table de huffman est la même pour tous les fichiers, ce qui aurait du sens si les fichiers sont tous similaires les uns aux autres.
finnw le

1
Si vous avez beaucoup de petits fichiers similaires, vous faites tout de travers. Tout d'abord, concaténez-les tous (comme le fait tar), puis compressez-les. Vous obtiendrez une meilleure compression et le problème cessera d'être "50-1000 octets".
Daniel C. Sobral

8
@Daniel: dépend si vous voulez un accès aléatoire aux données compressées. Compresser le tout ensemble empêche cela avec la plupart des systèmes de compression.
Steve Jessop

22

Je n'ai pas de code sous la main, mais j'ai toujours aimé l'approche consistant à créer une table de recherche 2D de taille 256 * 256 caractères ( RFC 1978 , PPP Predictor Compression Protocol ). Pour compresser une chaîne, vous bouclez sur chaque caractère et utilisez la table de recherche pour obtenir le prochain caractère «prédit» en utilisant le caractère actuel et précédent comme index dans la table. S'il y a une correspondance, vous écrivez un seul bit, sinon écrivez un 0, le char et mettez à jour la table de recherche avec le char actuel. Cette approche maintient essentiellement une table de recherche dynamique (et brute) du caractère suivant le plus probable dans le flux de données.

Vous pouvez commencer avec une table de recherche à zéro, mais évidemment, elle fonctionne mieux sur des chaînes très courtes si elle est initialisée avec le caractère le plus probable pour chaque paire de caractères, par exemple pour la langue anglaise. Tant que la table de recherche initiale est la même pour la compression et la décompression, vous n'avez pas besoin de l'émettre dans les données compressées.

Cet algorithme ne donne pas un taux de compression brillant, mais il est incroyablement économe en mémoire et en ressources CPU et peut également fonctionner sur un flux continu de données - le décompresseur conserve sa propre copie de la table de recherche lors de la décompression, donc la table de recherche s'adapte au type de données compressées.


Mais comment le prédicteur se comporterait-il avec une phrase anglaise normale? L'exemple donné a une redondance très forte et le gain est minime.
Danubian Sailor le

Une table de consultation 256 * 256 ne semble pas "incroyablement frugale avec la mémoire" ...!
MikeW

@MikeW Eh bien, c'est 65 kilo-octets.
redcalx

@redcalx Si cela avait été 65 octets, j'aurais pu être d'accord!
MikeW

11

Tout algorithme / bibliothèque prenant en charge un dictionnaire prédéfini, par exemple zlib .

De cette façon, vous pouvez amorcer le compresseur avec le même type de texte qui est susceptible d'apparaître dans l'entrée. Si les fichiers sont similaires d'une manière ou d'une autre (par exemple, toutes les URL, tous les programmes C, toutes les publications StackOverflow, tous les dessins ASCII-art) alors certaines sous-chaînes apparaîtront dans la plupart ou tous les fichiers d'entrée.

Chaque algorithme de compression économisera de l'espace si la même sous-chaîne est répétée plusieurs fois dans un fichier d'entrée (par exemple "the" en texte anglais ou "int" en code C.)

Mais dans le cas des URL, certaines chaînes (par exemple " http: // www .", ".Com", ".html", ".aspx" apparaîtront généralement une fois dans chaque fichier d'entrée. Vous devez donc les partager entre les fichiers. plutôt que d'avoir une occurrence compressée par fichier. Les placer dans un dictionnaire prédéfini y parviendra.


2
Conseils sur l'utilisation du dictionnaire personnalisé: stackoverflow.com/questions/2011653
Trenton


4

Si vous parlez de compresser le texte, pas seulement de raccourcir, puis Deflate / gzip (wrapper autour de gzip), zip fonctionne bien pour les fichiers et le texte plus petits. D'autres algorithmes sont très efficaces pour les fichiers plus volumineux comme bzip2, etc.

Wikipedia a une liste des temps de compression. (cherchez une comparaison d'efficacité)

Name       | Text         | Binaries      | Raw images
-----------+--------------+---------------+-------------
7-zip      | 19% in 18.8s | 27% in  59.6s | 50% in 36.4s
bzip2      | 20% in  4.7s | 37% in  32.8s | 51% in 20.0s
rar (2.01) | 23% in 30.0s | 36% in 275.4s | 58% in 52.7s
advzip     | 24% in 21.1s | 37% in  70.6s | 57& in 41.6s
gzip       | 25% in  4.2s | 39% in  23.1s | 60% in  5.4s
zip        | 25% in  4.3s | 39% in  23.3s | 60% in  5.7s

6
Il veut compresser du texte et non des fichiers.
Gumbo le

3
Vous pouvez compresser du texte et des binaires avec ces algorithmes. En fait, nous utilisons deflate dans un système cms qui s'exécute en python.
Ryan Christensen le

Un exemple en C # utilisant gzip pour les chaînes est ici: csharphelp.com/archives4/archive689.html
Ryan Christensen

module zlib en python pour la compression de chaînes: python.org/doc/2.5.2/lib/module-zlib.html
Ryan Christensen

3
gzip (et zlib) utilise deflate et ajoute une surcharge d'encapsulation / d'encadrement. Direct deflate / LZ77 (la surcharge et l'efficacité du dictionnaire dépendent toujours de l'implémentation de tels paramètres et) peut réduire la surcharge du seuil de rentabilité. Ceci est pour les chaînes "courtes" dans les dizaines à des centaines de caractères, bien sûr (devrait encore avoir un bit pour indiquer "était-ce compressé"? Pour éviter d'agrandir les données). Une surcharge supplémentaire n'a pas d'importance ... à mesure que le texte augmente. Les chiffres affichés ici semblent concerner de gros fichiers texte (plusieurs secondes à courir!), Tandis que OP demande 50 à 1000 chartes - très petites en comparaison.
user2864740

2

Vous voudrez peut-être jeter un œil au schéma de compression standard pour Unicode .

SQL Server 2008 R2 l'utilise en interne et peut atteindre jusqu'à 50% de compression.


SCSU «compresse» Unicode non anglais dans les encodages UTF-16 / MB. Si Unicode / plain-old-ASCII basé en anglais, UTF-8 «compresse» également 50% de UTF-16 ..
user2864740
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.