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


    由于自己还是非常喜欢字典树这个数据结构,每次都觉得很有高级的感觉,在此将自己做练习期间遇到的字典树的模板做一下记录。下面两个基本上是一种模板,都是用到了插入以及搜索的过程中,用到了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;
        }    
    };
    
  • 相关阅读:
    配置IVR实现语音
    建立SIP通话
    安装FreePBX的ISO版本
    Redis在linux环境下的安装
    上传文件漏洞
    忘记密码漏洞
    常见Web安全漏洞--------CSRF
    Api接口幂等设计
    常见Web安全漏洞--------防盗链
    常见Web安全漏洞--------sql注入
  • 原文地址:https://www.cnblogs.com/wsl-hitsz/p/13753852.html
Copyright © 2020-2023  润新知