Problema G - The Burrow Wheeler Transform |
Autor: Paul Crocker e Simão Sousa (Universidade da Beira Interior)
Tipo de problema: Cifra/Ordenação/Ad-Hoc
A transformação de Burrows-Wheeler, também conhecida como "block-sorting compression" é uma técnica clássica usada em muitos conhecidos algoritmos de compressão. À primeira vista, não parece completamente óbvio que se consiga fazer a transformação inversa, mas tal é perfeitamente possível.
Consideremos o exemplo de input, onde é dado "rdarcaaaabb 2". Se começarmos por ordenar as letras, conseguimos saber a primeira coluna da tabela ordenada de rotações da palavra (a última coluna é o input, e 2 é a posição da palavra, também dada no input).
0 a.........r 1 a.........d 2 a.........a -> palavra original 3 a.........r 4 a.........c 5 b.........a 6 b.........a 7 c.........a 8 d.........a 9 r.........b 10 r.........b
Seja next[i]=j se i é uma linha da tabela e j é a linha que corresponde à rotação seguinte na palavra original.
Como as entradas da tabela correspondem a rotações da palavra, sabemos a seguir à última letra de uma linha vem a letra do início da mesma linha. Isto permite-nos inferir relações. Por exemplo, como só existe um 'c' na palavra, então next[7]=4, pois 'c' é o primeiro caracter da linha 7 e a única linha que termina em 'c' é a linha 4. Mas o que acontece quando os caracteres não são únicos?
Felizmente, não existe ambiguidade. Mesmo possa não ser muito intuitivo, a verdade é que todas as linhas que terminam com um mesmo caracter estão também ordenadas! Ou seja, a primeira linha que começa com a letra 'a', tem como next a primeira linha que termina em 'a', e por aí adiante. Porquê? Precisamente porque a tabela tem as linhas ordenadas. Para perceber melhor veja a seguinte tabela "completa":
i NEXT[i] 0 aabracadabr 2 1 abraabracad 5 2 abracadabra 6 3 acadabraabr 7 4 adabraabrac 8 5 braabracada 9 6 bracadabraa 10 7 cadabraabra 4 8 dabraabraca 1 9 raabracadab 0 10 racadabraab 3
Tendo next[i] calculado, passa a ser trivial reproduzir a palavra original, bastando começar na linha dada no input e seguindo os next[i] respectivos.
Ligações interessantes: