Trie树
Trie树是一种字典树,它可以用来保存单词,查找单词。
用边来表示字符(如字母);则节点表示字符串,其由从根节点到当前节点的路径上的符号连接而成。
在实现上,对节点编号,将单词节点标记为1,否则标记为0。对字符集也进行编号,则可以建立数组ch[max_node][sigma_size]
,用以表示节点通过字符所连接的子节点。
代码
#include <iostream>
#include <string>
using namespace std;
const int MAXN = 1e5;
const int SIGMA_SIZE = 26;
// 节点的附加信息,例如是否单词(终点).
struct NodeInf
{
bool is_word;
};
class Trie
{
private:
// static const int MAXN, SIGMA_SIZE;
int childs[MAXN][SIGMA_SIZE]; // 节点的儿子信息
NodeInf val[MAXN]; // 节点附加信息
int size; // 节点数量
void node_init(NodeInf node, bool is_end); // 节点初始化, (根据具体情况设定,此处分是否单词结尾)
int getIdx(char ch); // 获取字符索引, 映射char->int
public:
Trie()
{
memset(childs[0], 0, sizeof(childs[0]));
node_init(val[0], 1);
size = 1;
}
// 插入新单词
void insert(string word)
{
int cur_node = 0;
for (int ch:word)
{
int idx = getIdx(ch); // 该字符对应的索引
if (childs[cur_node][idx] == 0) // 新前缀,新增节点
{
memset(childs[size], 0, sizeof(childs[size]));
node_init(val[size], false); // 中间节点赋值
childs[cur_node][idx] = size++;
}
cur_node = childs[cur_node][idx];
}
node_init(val[cur_node], true); // 单词终点赋值
}
// 搜索单词
bool search(string word) {
int cur_node = 0;
for (int ch:word)
{
int idx = getIdx(ch);
if (childs[cur_node][idx] == 0) return false;
cur_node = childs[cur_node][idx];
}
return val[cur_node].is_word;
}
};
LeetCode208. Implement Trie (Prefix Tree)
Implement a trie with insert, search, and startsWith methods.
class Trie {
private:
static const int MaxNode = 40000;
int child[MaxNode][26];
bool val[MaxNode];
int size;
public:
/** Initialize your data structure here. */
Trie() {
size = 1;
memset(child[0], 0, sizeof(child[0]));
val[0] = true;
}
/** Inserts a word into the trie. */
void insert(string word) {
int cur_node = 0;
for (int ch:word)
{
if (child[cur_node][ch-'a'] == 0) // 新前缀,新增节点
{
memset(child[size], 0, sizeof(child[size]));
val[size] = false;
child[cur_node][ch-'a'] = size++;
}
cur_node = child[cur_node][ch-'a'];
}
val[cur_node] = true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
int cur_node = 0;
for (int ch:word)
{
if (child[cur_node][ch-'a'] == 0) return false;
cur_node = child[cur_node][ch-'a'];
}
return val[cur_node];
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
int cur_node = 0;
for (int ch:prefix)
{
if (child[cur_node][ch-'a'] == 0) return false;
cur_node = child[cur_node][ch-'a'];
}
return true;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
《算法竞赛入门经典训练指南》3.3.1