Suffix Tree (后缀树)、Suffix Array (后缀数组)、LZW树详细解读

news2024/11/26 14:08:45

一、后缀树(Suffix Tree)

1. 定义

后缀树是一种紧凑的前缀树(前缀树的特殊形式),用于表示字符串的所有后缀。它是一种能够快速完成字符串模式匹配的数据结构,适合解决子串搜索和模式匹配等问题。

2. 工作原理
  • 结构:后缀树由一个根节点和多个路径组成,每条路径表示一个字符串后缀。
  • 节点:每个叶节点代表一个字符串的后缀,节点存储该后缀在原字符串中的位置。
  • 路径压缩:在后缀树中,公共前缀路径只存储一次,这样能大幅减少空间占用。

构建后缀树的经典算法是 Ukkonen’s 算法,时间复杂度为 O(n),其中 n 是字符串长度。构建过程涉及字符串的逐字符插入和动态更新。

3. 特点
  • 压缩结构:利用路径压缩存储公共前缀,节省空间。
  • 高效查询:模式匹配、子串搜索等操作复杂度较低。
4. 优缺点
  • 优点
    • 高效子串搜索:能够在 O(m) 时间内完成长度为 m 的模式匹配。
    • 子串重复统计:能够快速找到字符串的最长重复子串。
  • 缺点
    • 高构建复杂度:尽管存在线性构建算法,但实现较为复杂。
    • 较高的空间占用:后缀树比后缀数组占用更多的内存。
5. 应用场景
  • DNA 序列分析:用于检测基因序列中的特定模式。
  • 信息检索:例如全文搜索、关键字检索。
  • 压缩算法:如 Burrows-Wheeler 变换(BWT)。
6. 示例代码

在 Java 中实现后缀树较为复杂,以下是其构造的基本概念(实际中 Ukkonen’s 算法更常用)。

class SuffixTreeNode {
    Map<Character, SuffixTreeNode> children = new HashMap<>();
    int start, end;

    public SuffixTreeNode(int start, int end) {
        this.start = start;
        this.end = end;
    }
}

class SuffixTree {
    private String text;
    private SuffixTreeNode root;

    public SuffixTree(String text) {
        this.text = text;
        root = new SuffixTreeNode(-1, -1);
        buildSuffixTree();
    }

    private void buildSuffixTree() {
        for (int i = 0; i < text.length(); i++) {
            insertSuffix(i);
        }
    }

    private void insertSuffix(int index) {
        SuffixTreeNode node = root;
        for (int i = index; i < text.length(); i++) {
            char ch = text.charAt(i);
            node.children.putIfAbsent(ch, new SuffixTreeNode(i, text.length()));
            node = node.children.get(ch);
        }
    }
}

二、后缀数组(Suffix Array)

1. 定义

后缀数组是一种包含字符串所有后缀按字典序排序的数组。它提供了一种较为紧凑的方式来索引字符串中的子串位置,具有空间高效和较高查找效率的特点。

2. 工作原理
  • 数组结构:后缀数组由一个整数数组组成,每个元素存储字符串对应后缀的起始位置。
  • 构建过程:将字符串的所有后缀按字典序排序,然后记录排序后的起始位置。典型的构建算法如 Manber 和 Myers 算法,时间复杂度为 O(nlog⁡n)。
3. 特点
  • 紧凑表示:仅使用一个整数数组,不使用树结构,因此内存占用少。
  • 效率高:查找和排序后缀的时间复杂度低。
4. 优缺点
  • 优点
    • 空间高效:比后缀树更紧凑,适合内存敏感的应用。
    • 快速匹配:通过二分查找进行模式匹配,复杂度为 O(mlog⁡n)。
  • 缺点
    • 查找速度稍逊:模式匹配速度较后缀树稍慢,尤其是长字符串。
    • 构建复杂度较高:构建后缀数组的时间复杂度略高于部分后缀树算法。
5. 应用场景
  • 字符串模式匹配:用于查找字符串中的特定模式。
  • 压缩算法:如 Burrows-Wheeler 变换和 FM 指数。
  • 全文检索:可用于快速查找大量文本中的特定子串。
6. 示例代码
import java.util.Arrays;

public class SuffixArray {
    private String text;
    private int[] suffixArray;

    public SuffixArray(String text) {
        this.text = text;
        this.suffixArray = new int[text.length()];
        buildSuffixArray();
    }

    private void buildSuffixArray() {
        int n = text.length();
        Integer[] indexes = new Integer[n];
        for (int i = 0; i < n; i++) {
            indexes[i] = i;
        }
        Arrays.sort(indexes, (a, b) -> text.substring(a).compareTo(text.substring(b)));
        for (int i = 0; i < n; i++) {
            suffixArray[i] = indexes[i];
        }
    }

    public int[] getSuffixArray() {
        return suffixArray;
    }
}

三、LZW树

1. 定义

LZW树是一种用于压缩的树结构,以实现 LZW(Lempel-Ziv-Welch)算法。LZW 算法是一种无损数据压缩算法,通过构建一个动态词典,将重复的模式编码为更短的形式。

2. 工作原理
  • 编码:LZW 通过维护一个词典,将重复出现的模式编码为单个代码。初始词典包含基本字符,随着压缩过程的进行,词典会动态增长,加入更多模式。
  • 树结构:在 LZW 算法中,树的结构表现为词典的扩展,每个节点代表一个符号或符号序列。
3. 特点
  • 动态扩展词典:随着压缩过程的进行,词典不断更新,能够适应不同类型的数据。
  • 无损压缩:能有效压缩数据而不丢失信息。
4. 优缺点
  • 优点
    • 适用多种数据:适合文本、图像等多种类型的数据压缩。
    • 效率高:能够有效减少文件大小。
  • 缺点
    • 词典空间开销:词典在压缩时需要占用一定的空间。
    • 压缩效率受数据特性影响:对于没有重复模式的随机数据,压缩效果有限。
5. 应用场景
  • 文件压缩:如图像格式 GIF。
  • 数据传输:压缩数据传输以减少带宽占用。
6. 示例代码

以下是 LZW 编码的 Java 实现示例:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class LZWCompression {
    public List<Integer> compress(String text) {
        HashMap<String, Integer> dictionary = new HashMap<>();
        for (int i = 0; i < 256; i++) {
            dictionary.put("" + (char) i, i);
        }

        String current = "";
        List<Integer> compressed = new ArrayList<>();
        int dictSize = 256;

        for (char ch : text.toCharArray()) {
            String combined = current + ch;
            if (dictionary.containsKey(combined)) {
                current = combined;
            } else {
                compressed.add(dictionary.get(current));
                dictionary.put(combined, dictSize++);
                current = "" + ch;
            }
        }

        if (!current.equals("")) {
            compressed.add(dictionary.get(current));
        }
        return compressed;
    }
}

总结比较

数据结构特点应用场景优点缺点
后缀树紧凑前缀树,存储所有后缀模式匹配、子串统计高效匹配操作、快速统计构建复杂,内存占用大
后缀数组按字典序存储后缀起始位置模式匹配、压缩算法空间高效,紧凑构建复杂度较高,匹配速度稍慢
LZW树动态词典树,用于数据压缩文件压缩、数据传输高效压缩、无损词典空间占用,效果依赖数据特性

后缀树和后缀数组用于字符串处理,适合不同的场景;而 LZW树则主要用于数据压缩和传输。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2247887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

车载测试核心知识点和面试题

今天为大家分享一下车载测试岗位面试的时候&#xff0c;一定会问的相关技术。这些工具在测试的工作中会用到&#xff0c;在面试中也会经常被问到。所以同学们一定要去实战操作&#xff0c;这样理解和吸收才会更加深刻。 一、车载仪表台架测试CANoe工具实战 我们知道&#xff…

C/C++逆向:虚函数逆向分析

虚函数&#xff08;Virtual Function&#xff09;是C中实现多态的一种机制&#xff0c;它允许在运行时通过基类的指针或引用调用派生类中的函数&#xff0c;而不是基类中的版本。虚函数通常与继承和多态结合使用。通过在基类中使用 virtual 关键字声明函数&#xff0c;允许派生…

es写入磁盘的过程以及相关优化

数据写入到内存buffer同时写入到数据到translog buffer,这是为了防止数据不会丢失每隔1s数据从buffer中refresh到FileSystemCache中,生成segment文件,这是因为写入磁盘的过程相对耗时,借助FileSystemCache,一旦生成segment文件,就能通过索引查询到了refresh完,memory bu…

linux部署Whisper 视频音频转文字

github链接&#xff1a;链接 我这里使用anaconda来部署&#xff0c;debian12系统&#xff0c;其他linux也同样 可以使用gpu或者cpu版本&#xff0c;建议使用n卡&#xff0c;rtx3060以上 一、前期准备 1.linux系统 链接&#xff1a;debian安装 链接&#xff1a;ubuntu安装 …

论文阅读:A Software Platform for Manipulating theCamera Imaging Pipeline

论文代码开源链接&#xff1a; A Software Platform for Manipulating the Camera Imaging Pipelinehttps://karaimer.github.io/camera-pipeline/摘要&#xff1a;论文提出了一个Pipline软件平台&#xff0c;可以方便地访问相机成像Pipline的每个阶段。该软件允许修改单个模块…

【科研绘图】Matplotlib 教学

以下是一个针对 Matplotlib 教学 的博客结构&#xff0c;按照分步骤教学方式撰写&#xff0c;以帮助读者从基础到高级逐步掌握 Matplotlib。 Matplotlib 教学&#xff1a;从基础到进阶绘图 Matplotlib 是 Python 中功能强大的数据可视化库&#xff0c;可以用来绘制多种类型的图…

【网络系统管理】2023年全国职业院校技能大赛:组策略--10套题组合--4

16、只有域管理员和IT部门员工可以登陆服务器 (1)计算机配置\策略\Windows设置\安全设置\本地策略\用户权限分配 17、创建ChinaSkills23为GPO管理员,加入到企业管理、域控管理员组 (1)gpmc.msc\林\域\%domain%--在这个域中创建GPO 18、为所有域用户设置漫游文件 (1)用…

钉钉授权登录

一.找开钉钉开发平台【钉钉开放平台 (dingtalk.com)】 二。点击菜单【应用开发】->左边【钉钉应用】->【创建应用】 三。创建应用-》保存成功后&#xff0c;点击自己【新建的应用】&#xff0c;进入详细页面 四。进入应用详细页面。左边【分享设置】 注意&#xff1a;进…

应用系统开发(14) 涡流检测系统硬件设计

涡流检测整体系统架构 涡流检测系统整体结构如上图 所示,DAC 转换与功率放大电路将数字正弦信号转 换为模拟正弦信号,为涡流探头提供正弦激励。互感式探头由两个线圈组成,一个作为 激励,另一个接收检测信号,AD 转换电路将传感器探头感应到的电压滤波放大,将电 压值调整到…

介绍一下strupr(arr);(c基础)

hi , I am 36 适合对象c语言初学者 strupr(arr)&#xff1b;函数是把arr数组变为大写字母 格式 #include<string.h> strupr(arr); 返回值为arr 链接分享一下arr的意义(c基础)(必看)(牢记)-CSDN博客 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #incl…

人工智能之数学基础:向量的基本知识

本文重点 向量的基本性质是线性代数和向量空间理论的核心,它们为向量运算提供了坚实的基础,并在物理、工程、计算机图形学等领域有着广泛的应用。本文对向量的一些基本知识进行介绍,帮助大家快速理解向量。 向量的定义与表示 向量是一个既有大小又有方向的量,通常用带箭…

Redis中的zset底层实现

文章目录 Redis中的zset底层实现一、引言二、zset的底层实现1、ziplist编码1.1、代码示例 2、skiplist编码2.1、代码示例 三、总结 Redis中的zset底层实现 一、引言 Redis的有序集合&#xff08;zset&#xff09;是一种非常强大的数据结构&#xff0c;它不仅能够存储元素&…

TSmaster CAN/CANFD 诊断(Diagnostic_CAN)

文章目录 1、Diagnostic TP 参数配置1.1 传输层参数&#xff1a;1.2 服务层参数1.3 Seed&Key 2、基础诊断配置2.1 添加/删除 服务2.2 配置 BasicDiagnostic 服务参数 3、诊断控制台4、自动诊断流程4.1 流程用例管理4.2 配置诊断流程&#xff08;UDS Flow&#xff09;4.2.1 …

大语言模型---LoRA中损失值的计算

文章目录 概要损失计算流程小结 概要 Llama-7B模型的LoRA微调训练中&#xff0c;通过使用Cross-Entropy Loss来度量模型输出的预测分布和真实标签分布之间的距离&#xff0c;来衡量模型的准确性。 本文主要介绍LoRA中损失值的计算流程。 Cross-Entropy Loss作用&#xff1a;是…

Linux笔记--基于OCRmyPDF将扫描件PDF转换为可搜索的PDF

1--官方仓库 https://github.com/ocrmypdf/OCRmyPDF 2--基本步骤 # 安装ocrmypdf库 sudo apt install ocrmypdf# 安装简体中文库 sudo apt-get install tesseract-ocr-chi-sim# 转换 # -l 表示使用的语言 # --force-ocr 防止出现以下错误&#xff1a;ERROR - PriorOcrFoundE…

使用 Nginx 在 Ubuntu 22.04 上安装 LibreNMS 开源网络监控系统

#LibreNMS 是一个功能强大的开源网络监控系统&#xff0c;它能够为你的网络性能和设备提供全面的监控。本文将引导你通过一系列步骤&#xff0c;在 Ubuntu 22.04 服务器上安装和配置 LibreNMS&#xff0c;使用 Nginx 作为 Web 服务器。 简介 LibreNMS 提供了对网络设备和性能…

elementUI非常规数据格式渲染复杂表格(副表头、合并单元格)

效果 数据源 前端代码 (展示以及表格处理/数据处理) 标签 <el-table :data"dataList" style"width: 100%" :span-method"objectSpanMethod"><template v-for"(item, index) in headers"><el-table-column prop"…

使用脚本实现hadoop-yarn-flink自动化部署

本文使用脚本实现hadoop-yarn-flink的快速部署&#xff08;单机部署&#xff09;。 环境&#xff1a;①操作系统&#xff1a;CentOS 7.6&#xff1b;②CPU&#xff1a;x86&#xff1b;③用户&#xff1a;root。 1.前置条件 把下面的的脚本保存到“pre-install.sh”文件&#x…

Linux系统编程之进程基础知识

概述 在Linux系统中&#xff0c;进程是指一个正在运行的程序实例。每个进程都有一个唯一的进程标识符&#xff0c;即PID&#xff0c;操作系统通过这个PID来唯一识别和管理各个进程。进程不仅仅是程序代码的运行实例&#xff0c;它还包含了程序运行时所需的各种资源&#xff0c;…

H.264/H.265播放器EasyPlayer.js网页全终端安防视频流媒体播放器关于iOS不能系统全屏

在数字化时代&#xff0c;流媒体播放器已成为信息传播和娱乐消遣的主流载体。随着技术的进步&#xff0c;流媒体播放器的核心技术和发展趋势不断演变&#xff0c;影响着整个行业的发展方向。 EasyPlayer播放器属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持…