Сжатие строк в Java [дубликаты]

1

Я написал фрагмент кода, который сжимает строки не числовых символов. например, "aabccccaaa" будет сжиматься до a2b1c4a3. Мне было интересно, способ, которым я достигаю этого, имеет эффективную асимптотику времени выполнения. Есть ли более эффективный способ достижения?

Приведенный ниже код:

public static String Compress(String s)
{
    if(s.length()<=2)
    {
        return s;
    }
    int org_length=s.length();
    String comp="";
    int i=0;
    while(i<org_length)
    {
        Integer lc=1;
        while(i+1<org_length && s.charAt(i)==s.charAt(i+1))
        {
            lc++;
            i++;

        }
        if(i>=org_length){
            comp=comp+s.charAt(s.length()-1)+1;
        }
        else{
        comp=comp+s.charAt(i)+lc.toString();
        }

        i++;
    }
    if(s.length()<=comp.length())
    {
        return s;
    }
    return comp;
}
  • 0
    Извините, не могли бы вы уточнить, вы спрашиваете, эффективен ли подход кодирования длин серий или есть более эффективный способ сжатия строк?
  • 2
    en.wikipedia.org/wiki/Run-length_encoding
Показать ещё 6 комментариев
Теги:
performance
algorithm

1 ответ

1

Счетчик while должен сравнивать символ начала группы, пока он не изменится, или конец строки не будет достигнут. Затем просто напишите символ начала группы и захваченную длину. Сложность должна быть O (n).

public String rleCompress (String str) {
    StringBuilder res = new StringBuilder();
    int len = str.length();
    for (int i = 0; i < len;) {
       char c = str[i];
       int l = 0;
       // Always will loop at least once.
       while (i < len && str[i] == c) {
         l++;
         i++;
       }
       res.append(c);
       res.append(l);
    }
    return res.toString();
}

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

Однако Run-Length Encoding (RLE) хорош только в очень специфических случаях - в основном, когда одно значение повторяется много раз. Как и в случае с представленными данными, он сжимается до 80%, но "ababababab" "сжимает" до 200% оригинала!

Для очень коротких (~ 4+ символов) строки SMAZ могут быть подходящими: "Smaz - это простая библиотека сжатия, подходящая для сжатия очень коротких строк". (Он предназначен для "текста на английском языке", поэтому он не подходит для этих данных.)

Для коротких строк (символы ~ 60+) реализация zlib/DEFLATE может быть более практичной. (Некоторые реализации DEFLATE создадут бесполезный большой словарь, если это не требуется, обязательно проверьте фактический "сжатый" размер и разрешите альтернативный режим или без сжатия).

  • 0
    @ElliottFrisch Еще раз спасибо!
  • 0
    но "ababababab" "сжал бы" до 200% оригинала! демонстрирует принципиальное отсутствие понимания кодировки длин серий. Существуют реализации, которые все еще сжимают это и хорошо ab5 до ab5 в этом случае. Кодирование длин серий не ограничивается повторением отдельных байтов, это метод, который также подходит для многобайтовых повторений, как я продемонстрировал здесь.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню