实现 Trie (前缀树)https://leetcode.cn/problems/implement-trie-prefix-tree/
思路:
如下图所示:前缀树是一颗将公共前缀放在同一条路径上的数据结构,其中以结点表示字符,同时在结点内部增设一个标志变量,表示是否有字符串使用该结点作为结尾.每个结点有26个指针,分别指向26个字母.
实现方式:
- 使用二维数组:二维数组被初始化为100000行,26列的形式,26列对应着26个字母,每个单元格内的数字,代表同一字符串中,下一个单元格所在的行数.如下图所示,分别表示字符串ace, gch的存储结果.图中字母在实际中并不存储,格子中只存储下一字符的行号.这里防止字母是为了说明是第几个格子.再创建一个和二维数组长度一样长的数组count,来记录当前结点被重复使用的次数,在判断是否是前缀时使用.同时使用index变量,记录当前使用的行数.
class Trie {
int N = 100009;
int trie[][] ;
int count[];
int index;
public Trie() {
trie = new int[N][26];
count = new int[N];
index = 0;
}
public void insert(String word) {
int p = 0;
char[] word1 = word.toCharArray();
for(char s:word1){
int u = s-'a';
if (trie[p][u] == 0) trie[p][u] = ++index;
//表示当前的格子没有被使用过,所以指向下个格子
p = trie[p][u];
}
count[p]++;//遍历完当前字符串整体,在结尾处标记
}
public boolean search(String word) {
int p = 0;
char[] word1 = word.toCharArray();
for (char s: word1){
int u = s - 'a';
if (trie[p][u] == 0) return false;//当前字符未在已插入的数据中出现过,所以返回false
p = trie[p][u];
}
return count[p] != 0;
}
public boolean startsWith(String prefix) {
int p = 0;
char[] word1 = prefix.toCharArray();
for (char s: word1){
int u = s - 'a';
if (trie[p][u] == 0) return false;
p = trie[p][u];
}
return true;
}
}
使用树的形式实现:
class Trie {
class TrieNode {
boolean end;
TrieNode[] tns = new TrieNode[26];
}
TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String s) {
TrieNode p = root;
for(int i = 0; i < s.length(); i++) {
int u = s.charAt(i) - 'a';
if (p.tns[u] == null) p.tns[u] = new TrieNode();
p = p.tns[u];
}
p.end = true;
}
public boolean search(String s) {
TrieNode p = root;
for(int i = 0; i < s.length(); i++) {
int u = s.charAt(i) - 'a';
if (p.tns[u] == null) return false;
p = p.tns[u];
}
return p.end;
}
public boolean startsWith(String s) {
TrieNode p = root;
for(int i = 0; i < s.length(); i++) {
int u = s.charAt(i) - 'a';
if (p.tns[u] == null) return false;
p = p.tns[u];
}
return true;
}
}
力扣https://leetcode.cn/problems/prefix-and-suffix-search/solution/by-lfool-hm7z/