Implement a trie with insert, search, and startsWith methods.
Note:
You may assume that all inputs are consist of lowercase letters a-z.
题意:实现一个字典树(前缀树),包含查找、插入功能。
参考文章:字典树(Prefix Tree)
注意:查找一个word是否在树里面,不仅要看是否能够找到这样一个路径,还要看最后一个char的标志位是否是结束标志位,不然这不表示一个word。
class TrieNode {
public:
char c;//节点的值
map<char,TrieNode*> child;//节点的孩子,
bool ed;//节点是否是一个word的结束标志
// Initialize your data structure here.
TrieNode(char tc) {//常规节点的初始化
c=tc;
ed=false;
}
TrieNode() {//用以根节点的初始化
}
};
class Trie {
public:
Trie() {
root = new TrieNode();
}
// Inserts a word into the trie.
void insert(string word) {//插入一个word
TrieNode *rt=root;
int i=0;
int n=word.length();
while(i<n)
{
map<char,TrieNode*>& mt=rt->child;
if(mt.find(word[i])!=mt.end())
{
rt=mt[word[i]];//word的每个字母可以在树中找到
}
else
{//若树中不存在,则建立新的节点,并将节点加入父节点的孩子map里面
rt=new TrieNode(word[i]);
mt[word[i]]=rt;
}
++i;
}
if(rt->ed==false)
{//word最后一个字母的节点的标志位,将其置为true,表示一个word在此结束
rt->ed=true;
}
}
// Returns if the word is in the trie.
bool search(string word) {
TrieNode* rt=root;
int i=0;
int n=word.length();
while(i<n)
{
map<char,TrieNode*> mt=rt->child;
if(mt.find(word[i])!=mt.end())
{
rt=mt[word[i]];
++i;
}
else
{
return false;//若word中的每个字母无法再树中遍历完,表示不存在
}
}
return rt->ed;//每个字母存在还需要查询标志位是否为true
}
// Returns if there is any word in the trie
// that starts with the given prefix.
bool startsWith(string prefix) {
TrieNode *rt=root;//查找是否有以prefix开头的word
int i=0;
int n=prefix.length();
while(i<n)
{
map<char,TrieNode*> mt=rt->child;
if(mt.find(prefix[i])!=mt.end())
{
rt=mt[prefix[i]];
++i;
}
else
{
return false;//无法遍历完,表示不存在
}
}
return isp(rt);//遍历完后查询后面的所有节点是否有标志位为true,为true才表示有一个完整的word
}
bool isp(TrieNode *rt)
{
if(rt->ed==true)
{
return true;
}
map<char,TrieNode*>::iterator it=rt->child.begin();
for(;it!=rt->child.end();++it)
{
if(isp(it->second))
{
return true;
}
}
return false;
}
private:
TrieNode* root;
};
// Your Trie object will be instantiated and called as such:
// Trie trie;
// trie.insert("somestring");
// trie.search("key");