Un algoritmo de compresión eficiente para cadenas de texto cortas [cerrado]

126

Estoy buscando un algoritmo para comprimir cadenas de texto pequeñas: 50-1000 bytes (es decir, URL). ¿Qué algoritmo funciona mejor para esto?

Vasily Korolev
fuente
1
¿Dónde quieres usar estas cadenas comprimidas?
Gumbo
1
¿Esto va hacia tinyurlso tiene algo que ver con el espacio de almacenamiento?
nik
66
Estoy interesado en un algoritmo para comprimir URL, la mejor relación de compresión es más importante que el costo de ejecución. No estoy interesado en servicios en línea como tinyurls o tr.im. Estoy buscando un algoritmo, no un servicio. No creas que ninguna otra información pueda ser útil ...
Vasily Korolev el
3
@Gumbo: "Algoritmos de compresión de texto para cadenas cortas" es suficiente para encontrar algos, ¿por qué está tan interesado en saber para qué sirven? Estoy seguro de que el OP podrá encontrar el que hace lo que quiere.
Dervin Thunk el
77
@Vasily, una pequeña pista: cada vez que haces una pregunta sobre SO en la forma de "¿Cuál es el mejor XYZ?", Tu pregunta casi seguramente recibirá votos para cerrar porque pedir lo mejor podría conducir a un producto innecesario comparaciones, o en el peor de los casos, incluso guerras de llamas. (Por lo general, solo se necesita un cambio muy pequeño para evitar eso: si hiciera la misma pregunta como "Por favor, sugiera un XYZ", no obtendría tantos votos finales, ¡aunque sea básicamente la misma pregunta!)
stakx - ya no contribuye el

Respuestas:

62

Echa un vistazo a Smaz :

Smaz es una biblioteca de compresión simple adecuada para comprimir cadenas muy cortas.

stvchu
fuente
17
Consulte github.com/antirez/smaz/blob/master/smaz.c : esta es una variante de codificación, no de compresión per se (al menos no del todo). Utiliza un diccionario estático de palabras y letras.
Roy Tinker
77
Nota: Este es el proyecto de antirez. Es uno de los principales autores de Redis y tiene una reputación muy fuerte de lanzar código de producción de alta calidad.
Homer6
77
El algoritmo smaz está optimizado para textos en inglés, por lo tanto, no funciona bien para cadenas aleatorias. He aquí algunos ejemplos ( 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
44
También eche un vistazo a una compresión más baja pero un algoritmo rápido shoco ed-von-schleck.github.io/shoco
Dickey Singh
Agregar mi biblioteca Unishox a la lista github.com/siara-cc/unishox . Funciona mejor que Smaz y Shoco y admite la compresión de cadenas UTF-8.
Arun
28

Huffman tiene un costo estático, la tabla Huffman, por lo que no estoy de acuerdo, es una buena opción.

Hay versiones adaptativas que eliminan esto, pero la tasa de compresión puede sufrir. En realidad, la pregunta que debe hacerse es "qué algoritmo para comprimir cadenas de texto con estas características". Por ejemplo, si se esperan largas repeticiones, una simple codificación Run-Lengh podría ser suficiente. Si puede garantizar que solo las palabras en inglés, los espacios, la puntuación y los dígitos ocasionales estarán presentes, entonces Huffman con una tabla de Huffman predefinida podría dar buenos resultados.

En general, los algoritmos de la familia Lempel-Ziv tienen muy buena compresión y rendimiento, y abundan las bibliotecas para ellos. Yo iría con eso.

Con la información de que lo que se está comprimiendo son URL, entonces sugeriría que, antes de comprimir (con cualquier algoritmo que esté fácilmente disponible), CODIFICARlos. Las URL siguen patrones bien definidos, y algunas partes son altamente predecibles. Al hacer uso de este conocimiento, puede codificar las URL en algo más pequeño para comenzar, y las ideas detrás de la codificación Huffman pueden ayudarlo aquí.

Por ejemplo, al traducir la URL en una secuencia de bits, puede reemplazar "http" con el bit 1 y cualquier otra cosa con el bit "0" seguido del protocolo real (o usar una tabla para obtener otros protocolos comunes, como https, ftp, archivo). El ": //" se puede descartar por completo, siempre que pueda marcar el final del protocolo. Etc. Lea sobre el formato de URL y piense en cómo se pueden codificar para ocupar menos espacio.

Daniel C. Sobral
fuente
44
No si la tabla huffman es la misma para todos los archivos, lo que tendría sentido si los archivos son todos similares entre sí.
finnw
1
Si tiene muchos archivos pequeños similares, lo está haciendo todo mal. Primero, concatenarlos a todos (como lo hace tar), y luego comprimir eso. Obtendrá una mejor compresión y el problema dejará de ser "50-1000 bytes".
Daniel C. Sobral
8
@Daniel: depende de si desea acceso aleatorio a los datos comprimidos. Comprimirlo todo junto evita eso con la mayoría de los sistemas de compresión.
Steve Jessop el
22

No tengo código a mano, pero siempre me gustó el enfoque de construir una tabla de búsqueda 2D de tamaño 256 * 256 caracteres ( RFC 1978 , PPP Predictor Compression Protocol ). Para comprimir una cadena, realice un bucle sobre cada carácter y use la tabla de búsqueda para obtener el siguiente carácter 'predicho' utilizando los caracteres actuales y anteriores como índices en la tabla. Si hay una coincidencia, escribe un solo 1 bit; de lo contrario, escriba un 0, el carácter y actualice la tabla de búsqueda con el carácter actual. Este enfoque básicamente mantiene una tabla de búsqueda dinámica (y cruda) del siguiente carácter más probable en el flujo de datos.

Puede comenzar con una tabla de búsqueda puesta a cero, pero obviamente funciona mejor en cadenas muy cortas si se inicializa con el carácter más probable para cada par de caracteres, por ejemplo, para el idioma inglés. Mientras la tabla de búsqueda inicial sea la misma para compresión y descompresión, no es necesario que la emita a los datos comprimidos.

Este algoritmo no proporciona una relación de compresión brillante, pero es increíblemente económico con recursos de memoria y CPU y también puede funcionar en un flujo continuo de datos: el descompresor mantiene su propia copia de la tabla de búsqueda a medida que se descomprime, por lo tanto, la tabla de búsqueda se ajusta al tipo de datos que se comprimen.

Redcalx
fuente
Pero, ¿cómo se comportaría el predictor con una oración en inglés normal? El ejemplo dado tiene una redundancia muy fuerte y la ganancia es mínima.
Danubian Sailor
Una tabla de búsqueda de 256 * 256 no suena "increíblemente frugal con memoria" ...!
MikeW
@MikeW Bueno, son 65 kilobytes.
redcalx
@redcalx Si hubiera sido 65 bytes, ¡podría haber estado de acuerdo!
MikeW
11

Cualquier algoritmo / biblioteca que admita un diccionario preestablecido, por ejemplo, zlib .

De esta forma, puede cebar el compresor con el mismo tipo de texto que probablemente aparezca en la entrada. Si los archivos son similares de alguna manera (por ejemplo, todas las URL, todos los programas C, todas las publicaciones de StackOverflow, todos los dibujos de arte ASCII), aparecerán ciertas subcadenas en la mayoría o en todos los archivos de entrada.

Cada algoritmo de compresión ahorrará espacio si la misma subcadena se repite varias veces en un archivo de entrada (por ejemplo, "el" en texto en inglés o "int" en el código C).

Pero en el caso de las URL, ciertas cadenas (por ejemplo, " http: // www .", ".Com", ".html", ".aspx" generalmente aparecerán una vez en cada archivo de entrada. Por lo tanto, debe compartirlas entre archivos de alguna manera, en lugar de tener una aparición comprimida por archivo, colocarlos en un diccionario preestablecido logrará esto.

finnw
fuente
2
Consejos sobre el uso del diccionario personalizado: stackoverflow.com/questions/2011653
Trenton
4

La codificación de Huffman generalmente funciona bien para esto.

Zifre
fuente
44
Esta no es una respuesta de solo enlace; sin el enlace, sigue siendo una respuesta válida.
SL Barth - Restablece a Mónica el
..y todavía no es una buena respuesta. (No se ha introducido suficiente información relevante.)
user2864740
4

Si está hablando de comprimir el texto, no solo acortarlo, entonces Deflate / gzip (envoltorio alrededor de gzip), zip funciona bien para archivos y texto más pequeños. Otros algoritmos son altamente eficientes para archivos más grandes como bzip2, etc.

Wikipedia tiene una lista de tiempos de compresión. (busque la comparación de la eficiencia)

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
Ryan Christensen
fuente
66
Quiere comprimir texto y no archivos.
Gumbo
3
Puede comprimir texto y binarios con estos algoritmos. De hecho, usamos deflate dentro de un sistema cms que se ejecuta en python.
Ryan Christensen el
Un ejemplo en C # usando gzip para cadenas está aquí: csharphelp.com/archives4/archive689.html
Ryan Christensen
Módulo zlib en python para comprimir cadenas: python.org/doc/2.5.2/lib/module-zlib.html
Ryan Christensen el
3
gzip (y zlib) usa desinflar y agrega envoltura / sobrecarga de encuadre ... la deflación directa / LZ77 (la sobrecarga del diccionario y la eficiencia aún dependen de la implementación de tal y configuración) pueden reducir la sobrecarga de equilibrio. Esto es para cadenas "cortas" de docenas a cientos de caracteres, por supuesto (¿aún debería tener un poco para indicar "¿estaba comprimido?" Para evitar ampliar los datos). La sobrecarga adicional más grande no importa ... a medida que aumenta el texto. Los números publicados aquí parecen ser para archivos de texto grandes (¡muchos segundos para ejecutarse!), Mientras que OP solicita 50-1000 cartas, muy pequeñas en comparación.
usuario2864740
2

Es posible que desee echar un vistazo al Esquema de compresión estándar para Unicode .

SQL Server 2008 R2 lo usa internamente y puede lograr hasta un 50% de compresión.

Le Hibou
fuente
SCSU 'comprime' Unicode no inglés en codificaciones UTF-16 / MB. Si Unicode en inglés / ASCII simple, UTF-8 también 'comprime' el 50% de UTF-16 ..
user2864740