前缀树
前缀树:
将一个字符串进行拆解,从根节点到叶节点来进行深度延伸,每次延伸都记录一个字符,其最大特点就是可以用来判断字符前缀的问题。
原理图:
p为经过这个点的字符串树,e为以这个点为结尾的字符串树
代码及解析:
1.基本类的构建:
1 public static class TrieNode{ 2 int pass;//记录有多少个编码字符经过该节点 3 int end;//记录有多少个编码字符已该节点为终止点 4 TrieNode[] nexts;//存放通往下一个节点路径上的字符是什么 5 //可以用HashMap<TrieNode,char>来表示,可以更节省空间 6 7 public TrieNode() { 8 pass = 0; 9 end = 1; 10 nexts = new TrieNode[26];//0--26分别表示是否有字符a--z的编码 11 } 12 } 13 14 public static class Trie{ 15 TrieNode root;//根节点 16 17 public Trie() { 18 root = new TrieNode(); 19 } 20 }
2.插入功能:
1 //根据所给的字符串来插入构造对应的前缀树 2 public void Insert(String str) { 3 if (str == null) { 4 return; 5 } 6 char[] chs = str.toCharArray(); 7 //从根节点出发构造,且这个字符串一定过根节点,所以root.pass++ 8 TrieNode node = root; 9 node.pass++; 10 for (int i = 0; i < chs.length; i++) {//遍历字符串中的所有字符进行构造 11 int index = chs[i] - 'a'; 12 if (node.nexts[index] == null) {//之前没有这条路就开辟一条路 13 node.nexts[index] = new TrieNode(); 14 } 15 node = node.nexts[index];//逐层深入进行构造 16 node.pass++; 17 } 18 node.end++; 19 }
3.删除功能:
1 //在前缀树中删除某一个字符串 2 public void delete(String str) { 3 if (Search(str) != 0) {//前缀树中之前插入过str字符串才可进行删除 4 char[] chs = str.toCharArray(); 5 TrieNode node = root; 6 node.pass--; 7 for (int i = 0; i < chs.length; i++) { 8 int index = chs[i] - 'a'; 9 node = node.nexts[index]; 10 if (--node.pass == 0) {//如果node.pass==0说明已该字符串为前缀的字符没有了, 11 //后续的后缀都可以全部释放 12 node = null; 13 return; 14 } 15 } 16 node.end--; 17 } 18 }
4.查询功能:
(1).查询整个字符串在前缀树插入过几次:
1 //查询一个字符串在前缀树中插入过几次 2 public int Search(String str) { 3 if (str == null) { 4 return 0; 5 } 6 char[] chs = str.toCharArray(); 7 TrieNode node = root; 8 for (int i = 0; i < chs.length; i++) { 9 int index = chs[i] - 'a'; 10 if (node.nexts[index] == null) { 11 return 0; 12 } 13 node = node.nexts[index]; 14 } 15 return node.end; 16 }
(2).查询字符串作为前缀的次数:
1 //查询当前字符串是做为多少个已插入的字符串的前缀 2 public int preSearch(String pre) { 3 if (pre == null) { 4 return root.pass; 5 } 6 TrieNode node = root; 7 char[] chs = pre.toCharArray(); 8 for (int i = 0; i < chs.length; i++) { 9 int index = chs[i] - 'a'; 10 if (node.nexts[index] == null) { 11 return 0; 12 } 13 node = node.nexts[index]; 14 } 15 return node.pass; 16 }