Эффективный алгоритм сжатия коротких текстовых строк [закрыто]

126

Я ищу алгоритм для сжатия небольших текстовых строк: 50-1000 байт (то есть URL-адресов). Какой алгоритм лучше всего подходит для этого?

Василий Королев
источник
1
Где вы хотите использовать эти сжатые строки?
Gumbo
1
Это tinyurlsчто-то связано с местом для хранения?
nik
6
Меня интересует алгоритм сжатия URL-адресов, наилучшая степень сжатия важнее эксплуатационных расходов. Не интересует онлайн-сервисы вроде tinyurls или tr.im. Я ищу алгоритм, а не услугу. Не думаю, что какая-либо другая информация может быть полезной ...
Василий Королев
3
@Gumbo: "Алгоритмы сжатия текста для коротких строк" достаточно для поиска алгоритмов, почему вам так интересно знать, для чего они нужны? Я уверен, что ОП сможет найти того, кто делает то, что он хочет.
Dervin Thunk
7
@Vasily, небольшая подсказка: всякий раз, когда вы задаете вопрос по SO в форме «Какой XYZ лучший ?», Ваш вопрос почти обязательно получит голоса для закрытия, потому что просьба о лучшем может привести к ненужному продукту сравнения или, в худшем случае, даже пламенные войны. (Обычно требуется очень небольшое изменение, чтобы этого избежать: если бы вы задали тот же вопрос, например: «Пожалуйста, предложите XYZ.», Вы не получите столько заключительных голосов, хотя это, по сути, тот же вопрос!)
stakx - больше не участвует

Ответы:

62

Проверьте Smaz :

Smaz - это простая библиотека сжатия, подходящая для сжатия очень коротких строк.

stvchu
источник
17
См. Github.com/antirez/smaz/blob/master/smaz.c - это вариант кодирования, а не сжатие как таковое (по крайней мере, не полностью). Он использует статический словарь слов и букв.
Рой Тинкер,
7
Примечание: это проект антиреза. Он один из основных авторов Redis и имеет очень прочную репутацию разработчика высококачественного производственного кода.
Homer6 05
7
Алгоритм smaz оптимизирован для английских текстов, поэтому не работает для случайных строк. Вот некоторые образцы ( 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
Также обратите внимание на более низкое сжатие, но более быстрый алгоритм shoco ed-von-schleck.github.io/shoco
Дики Сингх
Добавить мою библиотеку Unishox в список github.com/siara-cc/unishox . Он работает лучше, чем Smaz и Shoco, и поддерживает сжатие строк UTF-8.
arun
28

У Хаффмана есть статическая стоимость, таблица Хаффмана, поэтому я не согласен, что это хороший выбор.

Существуют адаптивные версии, в которых это устранено, но может пострадать степень сжатия. Собственно, вопрос, который вы должны задать, - это «какой алгоритм сжимать текстовые строки с такими характеристиками». Например, если ожидается долгое повторение, может быть достаточно простого кодирования Run-Lengh. Если вы можете гарантировать, что будут присутствовать только английские слова, пробелы, пунктиры и случайные цифры, то Хаффман с предварительно определенной таблицей Хаффмана может дать хорошие результаты.

В целом алгоритмы семейства Lempel-Ziv имеют очень хорошее сжатие и производительность, а библиотек для них предостаточно. Я бы пошел с этим.

Имея информацию о том, что сжимаются URL-адреса, я бы предложил, чтобы перед сжатием (с помощью любого легко доступного алгоритма) вы их КОДИФИРОВАТЬ. URL-адреса следуют четко определенным шаблонам, и некоторые их части очень предсказуемы. Используя эти знания, вы можете для начала кодировать URL-адреса во что-то меньшее, и идеи, лежащие в основе кодирования Хаффмана, могут вам здесь помочь.

Например, переводя URL-адрес в битовый поток, вы можете заменить «http» битом 1, а все остальное - битом «0», за которым следует фактический протокол (или использовать таблицу для получения других общих протоколов, таких как https, ftp, файл). Знак ": //" можно вообще отбросить, если вы можете отметить конец протокола. И т. Д. Прочтите о формате URL и подумайте, как их можно кодировать, чтобы они занимали меньше места.

Дэниел С. Собрал
источник
4
Нет, если таблица Хаффмана одинакова для всех файлов, что имело бы смысл, если бы все файлы были похожи друг на друга.
finnw
1
Если у вас много одинаковых небольших файлов, вы делаете все неправильно. Сначала объедините их все (как это делает tar), а затем сожмите. Вы получите лучшее сжатие, и проблема перестанет быть "50-1000 байт".
Дэниел С. Собрал
8
@Daniel: зависит от того, хотите ли вы произвольный доступ к сжатым данным. Сжатие всего вместе предотвращает это в большинстве систем сжатия.
Стив Джессоп,
22

У меня нет кода под рукой, но мне всегда нравился подход к построению 2D-таблицы поиска размером 256 * 256 символов ( RFC 1978 , PPP Predictor Compression Protocol ). Чтобы сжать строку, вы перебираете каждый символ и используете таблицу поиска, чтобы получить «предсказанный» следующий символ, используя текущий и предыдущий символы в качестве индексов в таблице. Если есть совпадение, вы записываете один бит 1, в противном случае пишете 0, символ и обновляете таблицу поиска текущим символом. Этот подход в основном поддерживает динамическую (и грубую) таблицу поиска наиболее вероятного следующего символа в потоке данных.

Вы можете начать с обнуленной таблицы поиска, но очевидно, что она лучше всего работает с очень короткими строками, если она инициализирована наиболее вероятным символом для каждой пары символов, например, для английского языка. Если исходная таблица поиска одинакова для сжатия и распаковки, вам не нужно передавать ее в сжатые данные.

Этот алгоритм не дает блестящей степени сжатия, но он невероятно бережлив с памятью и ресурсами ЦП, а также может работать с непрерывным потоком данных - декомпрессор поддерживает свою собственную копию таблицы поиска при распаковке, таким образом, таблица поиска подстраивается под тип сжимаемых данных.

redcalx
источник
Но как бы предсказатель повел себя с нормальным английским предложением? В данном примере очень сильная избыточность, а выигрыш минимален.
Danubian Sailor
Таблица поиска 256 * 256 не звучит «невероятно экономно с памятью» ...!
MikeW
@MikeW Ну это 65 килобайт.
redcalx
@redcalx Если бы это было 65 байт, я бы согласился!
MikeW
11

Любой алгоритм / библиотека, поддерживающая предустановленный словарь, например zlib .

Таким образом, вы можете заполнить компрессор тем же текстом, который может появиться во входных данных. Если файлы в чем-то похожи (например, все URL-адреса, все программы на C, все сообщения StackOverflow, все рисунки в формате ASCII), то определенные подстроки появятся в большинстве или во всех входных файлах.

Каждый алгоритм сжатия экономит место, если одна и та же подстрока повторяется несколько раз в одном входном файле (например, «the» в английском тексте или «int» в коде C.)

Но в случае URL-адресов определенные строки (например, « http: // www .», «.Com», «.html», «.aspx» обычно появляются один раз в каждом входном файле. Таким образом, вам необходимо поделиться ими между файлами. каким-то образом вместо того, чтобы иметь по одному сжатому экземпляру для каждого файла - этого можно добиться, поместив их в предустановленный словарь.

finnw
источник
2
Советы по использованию настраиваемого словаря: stackoverflow.com/questions/2011653
Трентон,
4

Кодирование Хаффмана обычно подходит для этого.

Zifre
источник
4
Это не ответ только по ссылке; без ссылки это верный ответ.
SL Barth - Reinstate Monica
..и все еще не лучший ответ. (
Введено
4

Если вы говорите о фактическом сжатии текста, а не просто об его сокращении, тогда Deflate / gzip (оболочка вокруг gzip), zip хорошо работает для файлов и текста меньшего размера. Другие алгоритмы очень эффективны для больших файлов, таких как bzip2 и т. Д.

В Википедии есть список времен сжатия. (ищите сравнение эффективности)

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
Он хочет сжимать текст, а не файлы.
Gumbo
3
Вы можете сжимать текст и двоичные файлы с помощью этих алгоритмов. Фактически, мы используем deflate в системе cms, которая работает на Python.
Райан Кристенсен
Пример использования gzip для строк на C # приведен здесь: csharphelp.com/archives4/archive689.html
Райан Кристенсен
Модуль zlib в python для сжатия строк: python.org/doc/2.5.2/lib/module-zlib.html
Райан Кристенсен
3
gzip (и zlib) использует deflate и добавляет накладные расходы на оболочку / кадрирование. прямая deflate / LZ77 (накладные расходы словаря и эффективность все еще зависят от реализации таких параметров и настроек) может снизить накладные расходы безубыточности. Это, конечно, для «коротких» строк длиной от десятков до сотен символов (все же должен быть бит, чтобы указать, «было ли это сжато»? Во избежание увеличения данных). Большие дополнительные накладные расходы не имеют значения ... по мере увеличения текста. Цифры, размещенные здесь, похоже, относятся к большим текстовым файлам (много секунд для запуска!), В то время как OP запрашивает 50-1000 чартеров - очень мало для сравнения.
user2864740 03
2

Возможно, вы захотите взглянуть на стандартную схему сжатия для Unicode .

SQL Server 2008 R2 использует его для внутренних целей и может обеспечить сжатие до 50%.

Le Hibou
источник
SCSU «сжимает» неанглийский Unicode в кодировках UTF-16 / MB. Если английский Unicode / plain-old-ASCII, UTF-8 также «сжимает» 50% UTF-16 ..
user2864740 03