一文详解前缀树和其数组实现

本文详细介绍了前缀树的概念,包括如何添加和查找字符串,并通过Java数组模拟了前缀树的实现。文章还提供了具体的代码示例,并结合力扣实战题目讨论了在实际问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、何为前缀树

前缀树是一个利用字符串的公共前缀从而存储字符串列表的高级数据结构。

下图是一个前缀树示例图,首先可以看出前缀树除头结点以外的每个结点都包含两个属性:

  • 字符值
  • 以该字符为终点

![在这里插入图片描述](https://img-blog.csdnimg.cn/baa8be7ce0844086a1291cebc85c8067.pn

那么前缀树是如何存储字符串的呢,假如我们要搜"AEP"这个字符串,我们对这棵前缀树进行深度优先搜索,在搜索中间这条路径的"P"结点时,我们得到一条路径AEP,检查P结点的end值,值为1表示存在一个"AEP"字符串。
从而应该明白,这棵前缀树存储的字符串数组为:{“B”,“BQ”,“AE”,“AE”,“AEP”,“AED”,“D”}。

二、前缀树相关操作

1.添加字符串

假设我们需要添加"ABC","ABE"两个字符串

  1. 遍历字符串,并从头结点出发,若当前的子节点中不包含这个字符结点,新建一个结点并使其成为当前结点的子节点。
  2. 将当前结点指向这个子结点。
  3. 若这个子结点是字符串的结尾,其end加一。
  4. 循环123步骤直到遍历完字符串。

建树的过程如下:
在这里插入图片描述

2.查找字符串

查找步骤如下:

  1. 遍历字符串,并从头结点出发,若当前结点的子结点不存在这个字符结点,返回false;
  2. 使当前指针指向下一个子结点。
  3. 若已经遍历到字符串的末尾但该子结点end值为0,返回false、
  4. 循环123操作直到遍历完字符串。
  5. 返回true。

实际上查找过程就是一个剪枝的深度优先搜索。

三、数组模拟前缀树

假设字符串中仅存在小写字符。

1.定义数据结构

int[] son = new int[N][26];//模拟树结点
int[] cnt= new int[N];//模拟end
int idx = 0;//模拟指向可使用的内存的指针
  • 首先我们使用一个son数组来模拟结点,son有26列,表示可能有26个分支,假如son[i][1] = k:若k = 0,表示 i 这个结点不存在值为b的后代;若k!=0,不仅表示存在值为b的后代,而且这个后代结点为k。i = 0为头结点。
  • 用cnt数组模拟end的效果,cnt[i]的值即为以结点i为终点的字符串的个数。
  • idx指向当前可用的最后一格内存,每次新建一个结点时++idx,并为son赋值,即:son[i][j] = ++idx。

以上说明建议结合下面的具体操作代码理解。

2.数组模拟前缀树添加字符串

public void insert(String str){
   
    //插入一个字符串
    int h = 0;
    for(int i = 0;i<str.length();i++){
   
        int u = str.charAt(i) - 'a';
        if(son[h][u]==0) son[h][u] = ++idx;
        h = son[h][u];
    }

    cnt[h]++;
}

3.数组模拟前缀树查找字符串

public int query(String str){
   
    //查询str出现的次数
    int h = 0;
    for(int i = 0;i<str.length();i++){
   
        int u = str.charAt(i)-'a';
        if(son[h][u]<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值