前缀树 (prefix tree trie)
- 单个字符串中,字符从前到后的加到一棵多叉树上
- 字符放在路上,节点上有专属的数据项(常见的是pass和end值)
- 所有样本都这样添加,如果没有路就新建,如有路就复用
- 沿途节点的pass值增加1,每个字符串结束时来到的节点end值增加1
class Trie {
TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String str) {
if (str == null) {
return;
}
TrieNode curr = root;
root.pass++;
int path;
char[] arr = str.toCharArray();
for (char c : arr) {
path = c - 'a';
if (curr.nexts[path] == null) {
curr.nexts[path] = new TrieNode();
}
curr.nexts[path].pass++;
curr = curr.nexts[path];
}
curr.end++;
}
public int search(String str) {
if (str == null) {
return -1;
}
char[] arr = str.toCharArray();
int path;
TrieNode curr = root;
for (char c : arr) {
path = c - 'a';
if (curr.nexts[path] == null) {
return -1;
}
curr = curr.nexts[path];
}
return curr.end;
}
public void delete(String str) {
if (search(str) == -1) {
return;
}
char[] arr = str.toCharArray();
int path;
TrieNode curr = root;
for (char c : arr) {
path = c - 'a';
if (--curr.nexts[path].pass == 0) {
curr.nexts[path] = null;
return;
}
curr = curr.nexts[path];
}
curr.end--;
}
public int startsWith(String str) {
if (str == null) {
return -1;
}
char[] arr = str.toCharArray();
int path;
TrieNode curr = root;
for (char c : arr) {
path = c - 'a';
if (curr.nexts[path] == null) {
return -1;
}
curr = curr.nexts[path];
}
return curr.pass;
}
}
class TrieNode {
TrieNode[] nexts;
int pass;
int end;
public TrieNode() {
nexts = new TrieNode[26];
}
}