【数据压缩入门】字典转换

虽然 VLC 一直都在发挥作用,但它与熵绑定的事实也限制了数据压缩未来的发展。

学会分词

怎样才能决定哪些符号是最佳的“单词”?

可以通过被称为分词(tokenization)的过程找出这些“单词”,即分析一组数据并从中找出理想的“单词”。分词这一过程相当复杂,它本身也是信息论领域的一个研究分支。

@ Python jieba 库可以尝试代码分词

LZ 算法

工作原理

向前寻找匹配进行“分词”

  1. 搜索缓冲区
    • 将数据流分为两部分:search buffer & look ahead buffer
      ../../PHOTO/字典转换/img-20240915110535276.png|500
  2. 找到匹配
    |500
    ../../PHOTO/字典转换/img-20240915110658364.png|500
  3. 滑动窗口
    实际实现过程中,数据流因为其超长长度,难以对所有已处理过的符号进行搜索,因此需要对搜索缓冲区长度加以限制。
    ../../PHOTO/字典转换/img-20240915111011774.png|400
    有了滑动窗口,查找匹配的性能要求也就有了上限。同样也考虑到了局部性原理,即在给定的数据集中相关的数据很可能分布在相似的局部区域。

一般来说,搜索缓冲区滑动窗口的长度大概为几万个字节,而先行缓冲区的长度则只有几十个字节。

  1. 标记匹配
    通过偏移量和长度对匹配进行标记
    ../../PHOTO/字典转换/img-20240915111339104.png|500
  2. 未找到匹配情况
    需要对输出的记号进行修改,表明输出的是字面值,这样解码器就能读取并恢复源数据流。不过,怎样构造该记号完全取决于具体的 LZ 算法实现。一种最基本的做法是,将修改后的记号表示为三部分,还是偏移量和长度值,只不过取值都为 0,即 [0,0], 最后一部分则是符号的字面值
    ../../PHOTO/字典转换/img-20240915121803082.png|500

编码&解码

以字符串 TOBEORNOTTOBE 为例
../../PHOTO/字典转换/img-20240915140101726.png|400

这里编码的输出采用其他编码从而进一步编码成二进制,如 ASCII码

../../PHOTO/字典转换/img-20240915140126953.png|400

输出

例如上述用例,输出的记号集 [0,0,T] [0,0,O] [0,0,B] [0,0,E] [3,1] [0,0,R] [0,0,N] [3,1] [8,1] [9,4] 分成以下 3 个数据集:

针对数据集的处理:

算法变体

../../PHOTO/字典转换/img-20240915140000358.png|600

LZ77

LZ77 基本算法,有时也被称为 LZ1 算法;与前面介绍的唯一区别是,它会将先行缓冲区中下一个符号的字面值作为第三个值输出。

LZ78

LZ 算法系列的核心算法最早发表于 1977~1978 年,这两种算法有时也被称为 LZ1 算法和LZ2 算法。LZ78 算法的工作原理与前面描述的基本相同,不过它不用距搜索缓冲区结尾的偏移量来指示匹配的位置,而是根据输入流创建字典然后再引用。

LZW

LZW(Lempel-Ziv-Welch)算法是由 Terry Welch 于 1984 年提出的,它采用了 LZ78 算法的思想,其工作原理如下。

  1. LZW 算法将字典初始化为包含所有可能的输入字符,如果用到了清空和停止符号(clear and stop codes),那么这两个符号也包括在其中。
  2. 该算法扫描输入字符串以寻找更长的连续子串,直到它发现该子串在字典中不存在。
  3. 当发现这样的子串时,去掉它的最后一个符号(这样它就变成当前字典中最长的子串),然后从字典中找出其索引并输出。
  4. 将该子串(此时包括最后一个符号)加入字典作为新的词条。
  5. 将该子串的最后一个符号作为起点,重新扫描下一个子串。

该算法最适用于那些连续出现重复的数据。


© 2024 LiQ :) 由 Obsidian&Github 强力驱动