Основная трудность здесь заключается в «жадности» алгоритма и его неоднозначности. Учитывая ваш пример, каково правило, чтобы программа не представляла вашу строку как:
Д Х 1
Ababab X 1
CDA X 1
б х 1
Или еще хуже:
д х 1
abababcdab X 1
Вы понимаете, о чем я. Таким образом, вам нужно установить набор правил, которым будет следовать алгоритм, и тогда код будет писать сам. Чтобы получить представление об этом, вы можете попробовать взглянуть на код синтаксического анализа регулярного выражения в grep.c, хотя он может быть более продвинутым, чем вам нужно.
Для начала рассмотрим алгоритм, который:
- Ограничивает, насколько далеко он будет сканировать (т.е. устанавливать максимальную длину подстроки)
- Предпочитает более длинные подстроки, в зависимости от # 1
Например, возьмите "aaaaaaaaaaaaaaaa" (что составляет 16 а).
Это может быть любой из них:
X 16
AA X 8
аааа х 4
аааааааа Х 2
aaaaaaaaaaaaaaaa X 1
Если вы установите максимальную длину совпадения 4 и отдадите предпочтение самому длинному совпадению, тогда ответ будет однозначным: aaaa X 4. Теперь вы можете написать алгоритм.
Кстати, комментарий к алгоритму LZW (Lempel-Ziv-Welch) точный; это то, что делает этот алгоритм, хотя он динамически создает словарь по мере сканирования и пытается выразить более поздние элементы в терминах более ранних. Например:
аааааааааааааааа (опять 16 из них)
= bbbbbbbb (где b = aa)
= cccc (где c = bb)
= dd (где d = cc)
= е (где е = дд)
Это не совсем то, как работает LZW, но вы поняли.