数据结构与算法:字典树
本节目标:了解c语言和Python如何写前缀树
本节内容:前缀树
本节阅读需要(20)min。
本节实操需要(20)min。
前言
前缀树的本质其实是多分支多层次的字典。
一、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(最后一个视语言而定)