字典树,前缀树的模板!秒懂

由于自己还是非常喜欢字典树这个数据结构,每次都觉得很有高级的感觉,在此将自己做练习期间遇到的字典树的模板做一下记录。下面两个基本上是一种模板,都是用到了插入以及搜索的过程中,用到了this指针。this 指针的用法以后自己应该多思考一下,因该如何运用。


class Trie {
private:
    //数组初始化只有全为0才能这样写
    Trie* arc[27]={NULL};
    int val=0;
public:
    /** Initialize your data structure here. */
    Trie(){}

    /** Inserts a word into the trie. */
    void insert(string &word,int start,int _val) {
        Trie* p=this;
        int size=word.size();
        for (int i=start;i<size;++i)
        {
            int index= word.at(i)=='#' ? 26 : word.at(i)-'a';
            if (p->arc[index]==NULL)
                p->arc[index]=new Trie;
            p=p->arc[index];
            p->val=max(p->val,_val);
        }
    }

    int search(string &word) {
        Trie* p=this;
        int size=word.size();
        for (int i=0;i<size;++i)
        {
            int index= word.at(i)=='#' ? 26 : word.at(i)-'a';
            if (p->arc[index]==NULL)
                return -1;
            else
                p=p->arc[index];
        }
        return p->val;
    }
};
class WordFilter {
    Trie trie;
public:
    WordFilter(vector<string>& words) {
        int words_size=words.size();
        string s;
        for (int i=0;i<words_size;++i)
        {
            s=words.at(i)+"#"+words.at(i);
            int words_i_size=words.at(i).size();
            for (int j=0;j<=words_i_size;++j)
                trie.insert(s,j,i);
        }
    }

    int f(string prefix, string suffix) {
        string target=suffix+"#"+prefix;
        return trie.search(target);
    }
};
class MapSum {
public:
    /** Initialize your data structure here. */
    MapSum() {
        memset(child,0,sizeof(child));
        //isEnd=false;
        val=0;
        //sum=0;
    }

    void insert(string key, int val) {
        MapSum* ms=this;
        for(auto c:key){
            if(ms->child[c-'a']==NULL){
                ms->child[c-'a']=new MapSum();
            }
            //ms->sum+=val;
            ms = ms->child[c-'a'];
        }
        //ms->isEnd=true;
        ms->val=val;
        //ms->sum=val;
    }

    int sum(string prefix) {
        int ret=0;
        MapSum* ms=this;
        for(auto c:prefix){
            if(ms->child[c-'a']==NULL){
                return 0;
            }
            ms=ms->child[c-'a'];
        }
        ret+=ms->val;
        for(int i=0;i<26;i++){
            if(ms->child[i]==NULL) continue;
            ret+=ms->child[i]->sum("");
        }
        return ret;
    }
private:
    MapSum* child[26];
    //bool isEnd;
    int val;
    //int sum=0;
};

下面这个模板,更加的模块话,可用性更强。 在字典树的每一个节点可以设置一些标志位,例如isend 这样的bool 类型数据,这个数据就是看当然这个节点是不是某一个单词的结尾单词。

//字典树节点
class TrieNode{
private:
    bool isEnd;//单词结束标记
    int index;//单词序号
    vector<TrieNode*> children;//子节点
public:
    //构造
    TrieNode():index(-1),isEnd(false){
        children = vector<TrieNode*>(26, nullptr);
    }
    //析构
    ~TrieNode(){
        for(int i = 0;i < 26;i++)
        {
            if( children[i]) 
            {
                delete children[i];
                children[i] = nullptr;
            }
        }
    }
    //对外接口
    int getIndex() { return index;}
    void setIndex( int i) { index = i;}
    bool isWordEnd() { return isEnd;}
    void SetEnd(){ isEnd = true ;}
    //插入一个字符到子节点
    TrieNode* insertNode(char c) {
        if( !('a' <= c <= 'z') ) return nullptr;
        int id = c-'a'; 
        if( children[id] == nullptr ) {
            children[id] = new TrieNode();   
        }
        return children[id];
    }
    //在子节点中查找一个字符
    TrieNode* getNode(char c){
        if( !('a' <= c <= 'z') ) return nullptr;
        int id = c-'a';
        return children[id];
    }
};

//字典树
class Trie{
private:
    TrieNode * root;//根节点
public:
    Trie():root(new TrieNode()){}
    ~Trie() { delete root;}  
    //插入一个单词及序号
    void insert( string word,int index) {
        TrieNode * p = root;
        for(int i = 0; i < word.size(); i++){
            p = p->insertNode(word[i]);
        }
        p->SetEnd();
        p->setIndex(index);
    }
    //查找一个字符串
    TrieNode* getNode(string word) {
        TrieNode* p = root;
        for(int i = 0; i < word.size(); i++){
            p = p->getNode(word[i]) ;
            if( p == NULL ) return NULL;
        }
        return p;
    }
    //查找一个单词,返回序号
    bool  search(string word,int  &index) {
        TrieNode * p = getNode(word);
        if( p ) {
            index = p->getIndex();
            return  p->isWordEnd();
        }
        return false;
    }    
};

原文链接: https://www.cnblogs.com/wsl-hitsz/p/13753852.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    字典树,前缀树的模板!秒懂

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/397469

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月10日 上午9:33
下一篇 2023年4月10日 上午9:33

相关推荐