Быстрый поиск в сжатых текстовых файлах

Мне нужно иметь возможность поиска текста в большом количестве файлов (.txt), которые застегиваются. Сжатие может быть изменено на что-то другое или даже стать собственностью. Я хочу избежать распаковки всех файлов и сжатия (кодирования) строки поиска и поиска в сжатых файлах. Это должно быть возможно с помощью сжатия Huffman с одной и той же кодовой книгой для всех файлов. Я не хочу заново изобретать колесо .. кто-нибудь знает библиотеку, которая делает что-то вроде этого или алгоритма Хаффмана, который реализовано и протестировано, или, может быть, лучшая идея ?

спасибо заранее

5 ответов


большинство текстовых файлов сжимаются с помощью одного из LZ-семья алгоритмов, которые объединяют a Словарь Верстальщика вместе с Энтропийный Кодер например, Хаффмана.

поскольку кодер словаря опирается на постоянно обновляемый "словарь", его результат кодирования зависит от истории (все коды в словаре, которые получены из входных данных до текущего символа), поэтому невозможно перейти в определенное место и начать декодирование, без предварительного декодирования всех предыдущих данных.

на мой взгляд, вы можете просто использовать декодер потока zlib, который возвращает распакованные данные, не дожидаясь распаковки всего файла. Это не сэкономит время выполнения, но сохранит память.

второе предложение - сделать кодирование Хаффмана на английских словах и забыть о части Кодера словаря. Каждое английское слово сопоставляется с уникальным префиксом-free код.

наконец, @SHODAN дал самое разумное предложение, которое заключается в индексировании файлов, сжатии индекса и связывании со сжатыми текстовыми файлами. Чтобы выполнить поиск, распакуйте только индексный файл и найдите слова. Это на самом деле улучшение по сравнению с кодированием Хаффмана на словах - как только вы нашли частоту слов (чтобы оптимально назначить код префикса), вы уже построили индекс, поэтому вы можете сохранить индекс для поиска.


вряд ли вы сможете искать несжатые строки в сжатом файле. Я думаю, один из ваших лучших вариантов-как-то индексировать файлы. Возможно, с помощью Люсена?


поиск текста в сжатых файлах может быть быстрее, чем поиск того же самого в несжатых текстовых файлах.

один метод сжатия я видел, что жертвует некоторым пространством, чтобы сделать быстрый поиск:

  • ведение словаря с 2^16 записей каждого слова в тексте. Зарезервируйте первые 256 записей для литеральных байтов, на случай, если вы наткнетесь на слово, которого нет в словаре , хотя многие большие тексты имеют менее 32 000 уникальных слова, поэтому им никогда не нужно использовать эти литеральные байты.
  • сжатие исходного текста путем замены 16-разрядного индекса словаря для каждого слова.
  • (необязательно) в обычном случае, когда два слова разделены одним пробелом, отбросьте этот пробел; в противном случае поместите все байты в строке между словами в словарь как специальное "слово" (например,". "и", " и "\n"), помеченные атрибутом" нет пробелов по умолчанию", а затем "сжать" их строки, заменив их соответствующим индексом словаря.
  • поиск слов или фраз, сжимая фразу таким же образом, и поиск сжатой строки байтов в сжатом тексте точно так же, как вы искали бы исходную строку в исходном тексте.

в частности, поиск одного слова обычно сводится к сравнению 16-битного индекса в сжатом тексте, что быстрее, чем поиск этого слова в исходном тексте, потому что

  • каждое сравнение требует сравнения меньшего количества байтов -- 2, а не сколько байтов было в этом слове, и
  • мы делаем меньше сравнений, потому что сжатый файл короче.

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

(в принципе, вы можете заменить 16-битные коды фиксированной длины на префиксные коды Хаффмана переменной длины, как упоминал rwong-полученный сжатый файл будет меньше, но программное обеспечение для работы с этими файлами было бы немного медленнее и сложнее).

для более сложных техник, вы можете посмотреть


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


Это возможно, и может быть сделано достаточно эффективно. Существует много интересных исследований по этой теме, более формально известных как лаконичная структура данных. Некоторые темы, которые я бы рекомендовал изучить: вейвлет-дерево, FM-индекс/RRR, краткие массивы суффиксов. Вы также можете эффективно искать строки, закодированные Хаффманом, как показал ряд публикаций.