ブロックソート(BlockSorting/BWT)のアルゴリズム(^o^)

図解入門よくわかる最新データ圧縮技術の基本と仕組み (How‐nual Visual Guide Book)


abraca
この文字列をブロックソートし、復元してみる。


■1. エンコード手順
まず、巡回シフトしたデータを全て含む文字列テーブルを作成する。

1:abraca
2:aabrac
3:caabra
4:acaabr
5:racaab
6:bracaa

これを辞書順に並べ替えると。

1:aabrac
2:abraca
3:acaabr
4:bracaa
5:caabra
6:racaab

このようになる。このときの一番右の列を縦に並べた物がエンコードしたデータになる。
ここでは、

caraab(2)

これがエンコードデータになる。(2)は、元データ"abraca"が並べ替え後の何番目のデータであるかを表す。



■2. デコード手順
まず、caraabが一番右端のデータであることは分かっている。

1:?????c
2:?????a ←元データ
3:?????r
4:?????a
5:?????a
6:?????b

また、辞書順に並べ替えたので、一番左端は"caraab"を辞書順に並べた物と同じはずである。

1:a????c
2:a????a ←元データ
3:a????r
4:b????a
5:c????a
6:r????b

これを右シフトしてみる。
もともとシフトで生成したものなので、この2文字で始まる文字列がユニークに存在するはずである。

?:ca????
?:aa????
?:ra????
?:ab????
?:ac????
?:br????

これをソートしてみる。

1:aa????
2:ab????
3:ac????
4:br????
5:ca????
6:ra????

これは、ソート後のテーブルと一致しているはずである。
この右列にまたエンコードデータを追加してみる。

1:aa???c
2:ab???a
3:ac???r
4:br???a
5:ca???a
6:ra???b

ソート済みのテーブルに追加したので、問題ないはずである。
あとは繰り返し。
まずは右シフト。

?:caa???
?:aab???
?:rac???
?:abr???
?:aca???
?:bra???

ソート。

1:aab???
2:abr???
3:aca???
4:bra???
5:caa???
6:rac???

右列に追加

1:aab??c
2:abr??a ←元データ
3:aca??r
4:bra??a
5:caa??a
6:rac??b

右シフト。

?:caab??
?:aabr??
?:raca??
?:abra??
?:acaa??
?:brac??

ソート&右列に追加。

1:aabr?c
2:abra?a ←元データ
3:acaa?r
4:brac?a
5:caab?a
6:raca?b

右シフト。

?:caabr?
?:aabra?
?:racaa?
?:abrac?
?:acaab?
?:braca?

ソート&右列に追加。

1:aabrac
2:abraca ←元データ
3:acaabr
4:bracaa
5:caabra
6:racaab

これで、デコードデータ"abraca"が求められた。
以上が基本的な考え方である。


しかし、シフトするたびにソートしていたのでは重すぎる。
エンコード時にソート1回やるだけでも結構な負荷である。


そこで、巡回していることを利用してデコードを行う。


まず、1列目をソートしたデータがある。

1:a.....
2:a.....
3:a.....
4:b.....
5:c.....
6:r.....

これに番号を振る。

1:a1.....
2:a2.....
3:a3.....
4:b1.....
5:c1.....
6:r1.....

左シフトする。

1:.....a1
2:.....a2
3:.....a3
4:.....b1
5:.....c1
6:.....r1

これをソートすると。

1:a1.....c1
2:a2.....a?
3:a3.....r1
4:b1.....a?
5:c1.....a?
6:r1.....b1

このようになるはずである。
ここで、右の列のaは、ソートでどのように並び替えられたか分からないので、どの番号か分からなくなってしまう。
しかし実は、以下のように確定しているのである。

1:a1.....c1
2:a2.....a1
3:a3.....r1
4:b1.....a2
5:c1.....a3
6:r1.....b1

なぜか?
右シフトして考えてみる。

1:c1a1.....
2:a1a2.....
3:r1a3.....
4:a2b1.....
5:a3c1.....
6:b1r1.....

これをソートした場合、a1,a2,a3の順に並ばなければならないが、どうだろうか。
1列目a1の右にはa、1列目a2の右にはb、1列目a3の右にはcが来ている。
したがって、ソートすればa1,a2,a3の順に並ぶ。
これは偶然だろうか。
ここで2列目に着目する。
ソートしてから右シフトしたので、2列目はソートされている。
したがって、1列目が同じ文字に関しては2列目に従ってソートされるが、その際、元の順番は維持されたままになることが分かる。


よって

1:a1.....c1
2:a2.....a1 ←元データ
3:a3.....r1
4:b1.....a2
5:c1.....a3
6:r1.....b1

これを元にデコードをすることを考えると。
a2の次はなにかというと、4行目の右端にa2がある。4行目の左端はb1だがこれはサイクリックにつながっているので、

a2→b1

というのがわかる。
同様に続けていくと、

a2→b1→r1→a3→c1→a1

となる。
これにより、デコードデータ"abraca"が求められた。


以上の内容は下記ページを参照し、自分なりに分かりやすくまとめたつもり。


http://homepage3.nifty.com/DO/blocksorting.htm
http://wiki.osdev.info/?BlockSorting