2012-06-12 4 views
0

Я получил несколько мегабайт данных, как это:Обнаружения повторяющихся групп линий

11 2 1 
4 3 1 
11 2 1 
4 3 1 
11 2 1 
4 3 1 
18 3 2 

Я хотел бы, чтобы сжать его, добавив строки, говоря «предыдущие п строк повторяются т раз.» Алгоритм должен читать строки и задерживать их распечатку до нахождения максимально возможного m * n, но может принимать n < = 10. Какой был бы лучший способ сделать это?

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

+0

Вы можете подробно рассказать о технологии, которую вы используете, и о цели? если вы просто хотите сжать, вы можете использовать zip-алгоритмы, нет? – YavgenyP

+0

Я хочу, чтобы данные оставались читаемыми человеком. Linux syslog сжимает отдельные повторяющиеся строки таким образом, но я хотел бы также повторять последовательности групп из 2-10 строк, сжатых таким же образом. – jjrv

+0

Сжатие может быть выполнено, например, в awk, perl или C. Кроме того, в данных, отличных от повторов, мало корреляции. – jjrv

ответ

1

«копировать предыдущие n строк, повторенных m раз» - это ограниченная версия «copy k lines, начиная с j строк назад». Первый - второй с k = n * m и j = n. Более общая версия k, j - LZ77. (Хотя обычно это байты, а не линии.)

Алгоритмы LZ77 будут работать очень хорошо для этого. Подход хэш-таблицы, используемый gzip, zlib и т. Д., Быстро и легко кодируется. Сначала определите минимальное значение k (норка), которое вы считаете целесообразным, и определите, как далеко назад вы хотите искать совпадения, т. Е. Максимальное значение j (maxj). Затем постройте скользящее окно для линий maxj для поиска.

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

Используйте lazy-matching, где вы откладываете эмиссию матча, пока не обработает следующую строку, что может привести к более длинному совпадению.

+0

Спасибо! Я не знал, что LZ77 не создает словарь вроде LZW. Идеально подходит для моей цели. 200k строк ввода были суммированы в 30k. – jjrv

1

zip-алгоритмы могут сохранять читаемые данные. Они просто создают словари повторяющихся элементов (например, посмотрите на lempel - ziv). Я думаю, что алгоритм, как вы его описываете, может быть проблематичным. Ваша вторая строка отличается от вашей первой строки, так как вы узнаете, что вы должны рассматривать их как одну группу? когда вы ограничите группу и запустите новую?
Как вы можете сказать, что

11 2 1 
4 3 1 

действительно принадлежит к той же группе?

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

11 2 1 
4 3 1 
11 2 1 

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

key   : count 
11 2 1  : 3 
4 3 1  : 3 
11 2 1, 4 3 1: 3 
18 3 2  : 1 

Конечно, это требует более тонкой настройки, но я думаю, что этот алгоритм должен быть общее направление

+0

Lempel-Ziv выглядит несколько иначе, если бы у нас был, например, образец AABAAB согласно этой ссылке Википедии, он кодировал бы (0, A), (1, A), (2, B), (3, 0), и я хочу, чтобы он выводил AAB, 2. Проблема в том, что, увидев первый AA, он все равно ничего не выводит ... Кроме того, после каждой повторяющейся группы строк словарь должен быть пустым. – jjrv

+0

, если вы знаете, что у вас всегда есть пары или тройки строк, которые вам нужны, а затем используйте каждые 2 или 3 строки в качестве входных данных для алгоритма. Здесь, например, вы должны пройти AAB, а не A/AB. ваш случай, кажется, упрощает алгоритм, предполагая, что вы знаете, что повторяющиеся строки входят в конечные известные группы. – YavgenyP

+0

Размер повторяющегося раздела зависит от файла и обычно составляет 1-4 строки. – jjrv

0

Если вы думаете о файле, как долго строка, то я думаю, что ваша проблема заключается в нахождении longest repeated substring

Смежные вопросы