LZ77とは、記号列を走査し、繰り返し現れるパターンを検出して、それを圧縮するデータ圧縮アルゴリズムのことです。
このアルゴリズムは、LempelとZivによって1977年に提案されました。
LZ77による符号化の手順を説明する前に、用語の説明をします。
文字列など、記号の列のことです。例えば、「This is a pen.」などです。
記号列の連続した一部分をコピーしたものをスライド窓と呼びます。スライド窓は、参照部と符号化部で構成されます。
参照部とは、符号化部の先頭(左端)から始まる任意の長さの記号列と一致する記号列を探す領域のことです。ここで、参照部は、符号化済みの記号列の部分であり、圧縮する際に繰り返しパターンを見つけ出すために使用されます。
符号化部とは、符号化対象の記号列のことです。符号化部の記号列が、参照部内のどこかに出現しているかどうかを確認し、出現している場合はその情報を元に圧縮を行います。
LZ77による符号化の基本的な手順を以下に示します。
符号化する記号列をababcbababababababcbababababbabaとします。今回は、一つの記号を1バイトで表すこととします。よって、32バイトの記号列です。
まず、符号化部に記号列の先頭部分をコピーします。ここでは、参照部も符号化部も長さ(サイズ)は、14バイトとします。参照部の下には、記号位置を16進数で表示しています。
参照部には、この時点では何も入っていないのでスライド窓内の記号列全体を1バイト左にずらします。1バイトずらしたことによって空いた符号化部の領域には、記号列から続きの記号列をコピーします。そして、符号化データとして、aをそのまま出力します。(ここまでの符号化:a)
次に、bから始まる記号列は参照部にないのでスライド窓内の記号列全体を1バイト左にずらします。符号化データとして、00bを出力します。00は一致がなかったことを示す記号です。先ほど、aには00を付けませんでしたが、最初は必ず一致しないため、省略します。(ここまでの符号化:a00b)
今度は、abが参照部と最長一致しました。符号化データとして、C2cを出力します。Cは参照部における一致した記号列の開始位置、2は一致した長さです。cは一致した記号列の次の記号です。(ここまでの符号化:a00bC2c)
そして、符号化が完了した記号列が参照部に押し出されるようにスライド窓内の記号列全体を左にずらします。
次は、babが参照部と最長一致しました。符号化データとして、A3aを出力します。(ここまでの符号化:a00bC2cA3a)
そして、符号化が完了した記号列が参照部に押し出されるようにスライド窓内の記号列全体を左にずらします。
ここでは、babaが参照部と最長一致します。符号化データとして、A4bを出力します。(ここまでの符号化:a00bC2cA3aA4b)
そして、符号化が完了した記号列が参照部に押し出されるようにスライド窓内の記号列全体を左にずらします。
今度は、符号化部の全体が参照部と一致していますが、この場合は、最後の記号だけ不一致として扱います。よって、符号化データとして、0Dbを出力します。(ここまでの符号化:a00bC2cA3aA4b0Db)
そして、符号化が完了した記号列が参照部に押し出されるようにスライド窓内の記号列全体を左にずらします。参照部からはみ出た記号列は不要です。
babaは参照部に複数あります。ここでは一致記号列を参照部の先頭から検索しているので符号化データとして、54を出力します。符号化が完了しました。(最終的な符号化:a00bC2cA3aA4b0Db54)
参照部の記号位置と符号化部の一致長は、今回はそれぞれ4bitで表現できるので合わせて1バイトとします。よって、今符号化したa00bC2cA3aA4b0Db54は、12バイトとなります。
元の記号列が32バイトなので、12バイト/32バイトでデータのサイズが37.5%になりました。
符号化の手順から分かるように、逆参照を行えば、復号できます。先ほど符号化したa00bC2cA3aA4b0Db54を復号してみます。
まず、復号データとして、aを出力します。そして、以下のように参照部にaをコピーします。(ここまでの復号:a)
次に、00bは、不一致記号なので、復号データとして、bを出力します。そして、以下のように参照部にbをコピーします。(ここまでの復号:ab)
次に、C2cからabcを復号します。そして、以下のように参照部にabcをコピーします。(ここまでの復号:ababc)
次に、A3aからbabaを復号します。そして、以下のように参照部にbabaをコピーします。(ここまでの復号:ababcbaba)
次に、A4bからbababを復号します。そして、以下のように参照部にbababをコピーします。(ここまでの復号:ababcbabababab)
次に、0Dbからababcbababababを復号します。そして、以下のように参照部にababcbababababをコピーします。(ここまでの復号:ababcbababababababcbabababab)
最後に、54からbabaを復号します。復号が完了しました。(最終的な復号:ababcbababababababcbababababbaba)