前缀树:可创建一个虚拟的根节点,然后没插入一个树去不断地拓展下面的节点,以实现查找某个前缀是否出现过的功能。
但是要查找某个字符串是否出现过只能通过一个哈希set来最快的实现。
class Trie {
public:
//写一个结构体用来表示前缀树中的每一个节点
class Node{
public://构造函数默认构造值为0的节点
Node(int k=0):val(k){};
char val;//数值
vector<Node*> next;//对应指向下一层的节点的数组
};
//全局变量需要两个,一个是用来查找前缀的前缀树的虚拟头节点head,一个是用来存放已经插入过的字符串的哈希 set容器
Node* head;
unordered_set<string> insertwords;
Trie() {
head=new Node();//初始化的时候给虚拟头节点分配值
}
//插入的时候需要进行两次操作,一个操作时将插入的字符串插入到哈希set中
//另一个操作就是去从前缀树中查找是否已经建立了该字符串的前缀树
void insert(string word) {
if(insertwords.find(word)==insertwords.end())insertwords.insert(word);
Node* temp=head;
for(int i=0;i<word.length();++i)
{
bool find_sth=false;
for(int j=0;j<(temp->next).size();++j)//一层一层查找是否有对应的节点值
{
if((temp->next)[j]->val==word[i])
{
temp=(temp->next)[j];
find_sth=true;
break;
}
}
if(!find_sth){//如果到某一层没找到,那么下面就不可能找到了,所有从这个元素后面的元素
//都需要重新创建节点来插入到该层的前缀树下。
for(int k=i;k<word.length();++k)
{
(temp->next).push_back(new Node(word[k]));
temp=(temp->next)[(temp->next).size()-1];
}
break;
}
}
}
bool search(string word) {//查找是否插入过某个字符串只要查找该字符串是否出现在了哈希set中即可
return insertwords.find(word)==insertwords.end()?false:true;
}
bool startsWith(string prefix) {
Node* temp=head;
int n=prefix.size();
for(int i=0;i<n;++i)//查字典的每一层,一旦有一次没有出现过对应字母,那么肯定没有插入过该前缀
{
bool find_sth=false;
for(int j=0;j<(temp->next).size();++j)//找不到对应的就返回false
{
if((temp->next)[j]->val==prefix[i])
{
temp=(temp->next)[j];
find_sth=true;
break;
}
}
if(!find_sth)return false;
}
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);
*/