数据结构与算法:字典树(前缀树)

数据结构与算法:字典树

本节目标:了解c语言和Python如何写前缀树

本节内容:前缀树

本节阅读需要(20)min。
本节实操需要(20)min。



前言

1. 技能的意义所在。
2. 内容中概念的提出

前缀树的本质其实是多分支多层次的字典。


一、C版本的前缀树

节点的创建。

public class TrieNode {
	int count;
	int prefix;
	TrieNode[] nextNode=new TrieNode[26];
	public TrieNode(){
		count=0;
		prefix=0;
	}
}

TrieNode[] nextNode=new TrieNode[26]为什么是26,很简单,因为26个英文字母。也就是说只有有限的26种后缀。
并且通过数列的位置去编号字母的。

查询

//插入一个新单词
	public static void insert(TrieNode root,String str){
		if(root==null||str.length()==0){
			return;
		}
		char[] c=str.toCharArray();
		for(int i=0;i<str.length();i++){
			//如果该分支不存在,创建一个新节点
			if(root.nextNode[c[i]-'a']==null){
				root.nextNode[c[i]-'a']=new TrieNode();
			}
			root=root.nextNode[c[i]-'a'];
			root.prefix++;//注意,应该加在后面
			}
		
		//以该节点结尾的单词数+1
		root.count++;
	}
//查找该单词是否存在,如果存在返回数量,不存在返回-1
	public static int search(TrieNode root,String str){
		if(root==null||str.length()==0){
			return -1;
		}
		char[] c=str.toCharArray();
		for(int i=0;i<str.length();i++){
			//如果该分支不存在,表名该单词不存在
			if(root.nextNode[c[i]-'a']==null){
				return -1;
			}
			//如果存在,则继续向下遍历
			root=root.nextNode[c[i]-'a'];	
		}
		
		//如果count==0,也说明该单词不存在
		if(root.count==0){
			return -1;
		}
		return root.count;
	}
	
	//查询以str为前缀的单词数量
	public static int searchPrefix(TrieNode root,String str){
		if(root==null||str.length()==0){
			return -1;
		}
		char[] c=str.toCharArray();
		for(int i=0;i<str.length();i++){
			//如果该分支不存在,表名该单词不存在
			if(root.nextNode[c[i]-'a']==null){
				return -1;
			}
			//如果存在,则继续向下遍历
			root=root.nextNode[c[i]-'a'];	
		}
		return root.prefix;
	}

注意这里有两个数量。
一个是到这个节点为止的前缀字符串的数量。
一个是以这个节点为止的前缀的完整单词的数量。

二、Python版本的前缀树

class TreeNode(object):
    def __init__(self):
        self.nodes = {}         # 记录当前结点的子结点
        self.is_leaf = False   # 当前结点是否表示一个单词
        self.count = 0          # 单词树中单词的总量

    def insert(self,word):
        curr = self
        for c in word:
            if not curr.nodes.get(c,None):
                new_node = TreeNode()
                curr.nodes[c] = new_node
            curr = curr.nodes[c]
        curr.is_leaf = True
        self.count += 1
        return

    def insert_many(self,words):
        for word in words:
            self.insert(word)
        return

    def search(self,word):
        curr = self
        try:
            for c in word:
                curr = curr.nodes[c]
        except:
            return False
        return curr.is_leaf

总结

前缀树适用的场景。
1、低存储地维护字符串集合(即字典)。

2、向字符串集合中插入字符串(即建树)。

3、查询字符串集合中是否有某个字符串(即查询)。

4、统计字符串在集合中出现的个数(即统计)。

5、将字符串集合按字典序排序(即字典序排序)。

6、求集合内两个字符串的LCP(Longest Common Prefix,最长公共前缀)(即求最长公共前缀)

必须满足的条件:
1.后缀可能性是有限的。不然就是图了。
2.这些节点不重复,因为键名是不能重复的。

附目前发现的所有官标Hard实际难度为Easy的题目:154,273,745,829,987,1095,1220,1601,2151,2296(最后一个视语言而定)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

演技拉满的白马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值