C++字典树/Trie树模板总结

本文介绍了一种基于字典树的数据结构,探讨了其四个不同版本的设计,包括单词记录、位置索引、最小值追踪和动态计频。讲解了如何实现插入和搜索操作,并展示了在最大异或、前缀后缀搜索、回文对查找等场景中的应用实例。
摘要由CSDN通过智能技术生成

一. 基本结构

	class Tree {
	public:
	    bool isWord;
	    vector<Tree*> v;
	
	    /** Initialize your data structure here. */
	    Trie() {
	        isWord = false;
	        v.resize(26); //元素个数 全体小写字母26个
	    }
	};

1 需要返回单词string

	class Tree {
	public:
	    bool isWord;
	    string word;
	    vector<Tree*> v;
	
	    Tree() {
	        isWord = false;
	        word = "";
	        v.resize(26);
	    }
	};

2 记录位置idx

    class Tree{
    public:
        bool isWord;
        int idx;
        vector<Tree*> v;
        Tree() {
            isWord = false;
            idx = -1;
            v.resize(52);
        }
    };

3 记录当前最小值minv

    class Tree {
    public:
        bool isEnd;
        vector<Tree*> v;
        int minv;
        
        Tree() {
            isEnd = false;
            v.resize(2);
            minv = INT_MAX;
        };
    };

参考 1707. 与数组中元素的最大异或值

4 记录动态出现次数heat

    class Tree {
    public:
        bool isWord;
        vector<Tree*> v;
        string word;
        int heat;
        Tree() {
            isWord = false;
            v.resize(27);
            heat = -1;
        }
    };

参考 642. 设计搜索自动补全系统

二. 常用方法

1 插入

    void insert(Tree* t, const string &s) {
        for(char c : s) {
            if(!t->v[c - 'a'])
                t->v[c - 'a'] = new Tree();
            t = t->v[c - 'a'];
        }
        t->isWord = true;
        //t->word = s; // 需要返回单词string时 
        //t->idx = idx; // 需要记录位置idx时 
    }

2 搜索

(1)是否存在

    bool search(string word) {
        Trie* t = this;
        for(char c : word) {
            if(!t->v[c - 'a'])
                return false;
            t = t->v[c - 'a'];
        }
        return t->isWord;
    }

(2)各种DFS 略

三. 特殊应用

1 最大异或

int至多32位,按位(0、1)组成字典树

    class Tree {
    public:
        vector<Tree*> v;
        Tree(): v(2){};
        static void insert(Tree* t, int n, int L) {
            int p = 1 << (L - 1); //使用位与逐位插入
            while(p > 0) {
                int index = (p & n) ? 0 : 1;
                if(!t->v[index]) {
                    t->v[index] = new Tree();
                }
                t = t->v[index];
                p = p >> 1;
            }
        }
    };

2 前缀+后缀搜索

引入#作为前缀后缀中间过渡
插入时对每个字符串按(所有可能的)位分割,插入(前缀 + # + 后缀)

    class Tree {
    public:
        bool isWord;
        vector<Tree*> v;
        int weight;
        Tree() {
            isWord = false;
            v.resize(27);
            weight = -1;
        }
    };

    WordFilter(vector<string>& words) {
        this->root = new Tree();
        for(int k = 0; k < words.size(); k++) {
            string word = words[k];
            for(int i = 0; i < word.size(); i++) {
                string suffix = word.substr(i);
                string tmp = suffix + "#" + word;
                insert(this->root, tmp, k);
            }
        }
    }

3 回文对

查找使words[i]、words[j]组合称为回文串的回文对,使用记录idx的字典树
反序查找匹配回文串

    vector<vector<int>> palindromePairs(vector<string>& words) {
        tree.emplace_back(node());
        int n = words.size();
        for(int i = 0; i < n; i++)
            insert(words[i], i);
        vector<vector<int>> ret;
        for(int i = 0; i < n; i++){
            int m = words[i].size();
            for(int j = 0; j <= m; j++){
                if(isPalindrome(words[i], j, m - 1)){
                    int left_id = findWord(words[i], 0, j - 1);
                    if(left_id != -1 && left_id != i)
                        ret.push_back({i, left_id});
                }
                if(j && isPalindrome(words[i], 0, j - 1)){
                    int right_id = findWord(words[i], j, m - 1);
                    if(right_id != -1 && right_id != i)
                        ret.push_back({right_id, i});
                }
            }
        }
        return ret;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值