Trie树
上图表示一个trie树,有abc,abcd,abd,b,bcd,efg,hii七个字符串,红色点代表为一个字符串的最后一个字符。
上图同样表示一个trie树,有abc,d,da,dda四个字符串,字符串尾部同样进行了标记。
已知n个由小写字母构成的平均长度为10的字符串,判断其中是否存在某个串为另一个串的前缀子串,有三种方法:
1、遍历字符串集合,对于遍历的每两个字符串,判断其中一个是否为另一个的前缀子串,时间复杂度为O(n^2)。
2、使用hash,对于每一个字符串的所有前缀子串,进行hash,对于完整的字符串进行标记,然后再进行查询。其中建立hash的时间复杂度为O(n*len),而查询的时间复杂度为O(n)。
3、使用trie树,很自然的一个数据结构,可以建立的同时进行查询,其中建立trie树的时间复杂度为O(n*len),实际查询的复杂度为O(len)。
Trie树的实现代码,数据结构是上述第二幅图
#include <iostream> using namespace std; const int BranchNum=26; struct Trie_Node { bool isStr;//标记是否为完整字符串 Trie_Node* next[BranchNum]; Trie_Node() { isStr=false; for(int i=0;i<BranchNum;++i) next[i]=NULL; } }; class Trie { public: Trie(); void insert(const char* word); bool search(const char* word); void deleteTrie(Trie_Node* root); private: Trie_Node* root; }; Trie::Trie() { root=new Trie_Node; } void Trie::insert(const char* word) { Trie_Node* current=root; while(*word) { if(current->next[*word-'a']==NULL) { current->next[*word-'a']=new Trie_Node; } current=current->next[*word-'a']; word++; } current->isStr=true; } bool Trie::search(const char* word) { Trie_Node* current=root; while(*word && current) { current=current->next[*word-'a']; ++word; } return (current!=NULL && current->isStr); } void Trie::deleteTrie(Trie_Node* root) { for(int i=0;i<BranchNum;++i) if(root->next[i]) deleteTrie(root->next[i]); delete root; }