当前位置: 首页 > news >正文

数据结构与算法——字典(前缀)树的实现

参考视频:左程云--算法讲解044【必备】前缀树原理和代码详解

类实现:

class Trie {private:class TrieNode {public:int pass;int end;vector<TrieNode*> nexts;TrieNode(): pass(0), end(0), nexts(26, nullptr) {}};TrieNode* root;  // 根指针public:Trie() {root = new TrieNode();}void insert(const string& word) {TrieNode* node = root;node->pass++;int path;for(char c : word){path = c - 'a';if (node->nexts[path] == nullptr) {node->nexts[path] = new TrieNode();}node = node->nexts[path];node->pass++;}node->end++;}void mydelete(const string& word) {if (countWordsEqualTo(word) > 0) {TrieNode* node = root;node->pass--;int path;for (char c : word) {path = c - 'a';if (--node->nexts[path]->pass == 0) {funcDelete(node, path);return;}node = node->nexts[path];}node->end--;}}void funcDelete(TrieNode* node, int path) {TrieNode* target = node->nexts[path];node->nexts[path] = nullptr;delete (target);}bool search(const string& word) {return countWordsEqualTo(word) > 0 ? true : false;}int countWordsEqualTo(const string& word) {TrieNode* node = root;int path;for (char c : word) {path = c - 'a';if (node->nexts[path] == nullptr) {return 0;}node = node->nexts[path];}return node->end;}int prefixNumber(const string& pre) {TrieNode* node = root;int path;for (char c : pre) {path = c - 'a';if (node->nexts[path] == nullptr) {return 0;}node = node->nexts[path];}return node->pass;}
};

类实现基础上进行哈希表的优化:

class Trie {
private:class TrieNode {public:int pass;int end;unordered_map<int, TrieNode*> nexts;TrieNode() : pass(0), end(0) {}};TrieNode* root;  // 根指针public:Trie() {root = new TrieNode();}void insert(const string& word) {TrieNode* node = root;node->pass++;int path;for (char c : word) {path = c - 'a';if (node->nexts.find(path) == node->nexts.end()) {node->nexts.insert({ path, new TrieNode() });}node = node->nexts[path];node->pass++;}node->end++;}void mydelete(const string& word) {if (countWordsEqualTo(word) > 0) {TrieNode* node = root;node->pass--;int path;for (char c : word) {path = c - 'a';if (--node->nexts[path]->pass == 0) {node->nexts.erase(path);return;}node = node->nexts[path];}node->end--;}}bool search(const string& word) {return countWordsEqualTo(word) > 0 ? true : false;}int countWordsEqualTo(const string& word) {TrieNode* node = root;int path;for (char c : word) {path = c - 'a';if (node->nexts.find(path) == node->nexts.end()) {return 0;}node = node->nexts[path];}return node->end;}int prefixNumber(const string& pre) {TrieNode* node = root;int path;for (char c : pre) {path = c - 'a';if (node->nexts.find(path) == node->nexts.end()) {return 0;}node = node->nexts[path];}return node->pass;}
};

静态数组实现 + 牛客测试

测试链接:牛客题霸--字典树的实现

#include <bits/stdc++.h>
using namespace std;
const static int N = 1e6 + 5;
int trieArr[N][26];
int passArr[N];
int endArr[N];
int cnt;
void helpFunc(int op, string& word);
class trie{
public:void static buildTrie(){cnt = 1;}void static insert(const string& word){int cur = 1;passArr[cur]++;int path;for(char c : word){path = c - 'a';if(trieArr[cur][path] == 0){trieArr[cur][path] = ++cnt;}cur = trieArr[cur][path];passArr[cur]++;}endArr[cur]++;}int static searchCount(const string& word){int cur = 1, path;for(char c : word){path = c - 'a';if(trieArr[cur][path] == 0){return 0;}cur = trieArr[cur][path];}return endArr[cur];}bool static search(const string& word){return searchCount(word) > 0 ? true : false;}int static prefixCount(const string& pre){int cur = 1, path;for(char c : pre){path = c - 'a';if(trieArr[cur][path] == 0){return 0;}cur = trieArr[cur][path];}return passArr[cur];}void static deleteWord(const string& word){if(searchCount(word) > 0){int cur = 1, path;passArr[cur]--;for(char c : word){path = c - 'a';if(--passArr[trieArr[cur][path]] == 0){trieArr[cur][path] = 0;return;}cur = trieArr[cur][path];}endArr[cur]--;}}void static rebuildTrie(){for(int i = 1; i <= cnt; i++){fill(&trieArr[i][0], &trieArr[i][0] + 26, 0);passArr[i] = 0;endArr[i] = 0;}}
};int main() {int m;cin >> m;trie::buildTrie();while(m--){int op;string word;cin >> op >> word;helpFunc(op, word);}trie::rebuildTrie();return 0;
}void helpFunc(int op, string& word){switch(op){case 1 :trie::insert(word);break;case 2 :trie::deleteWord(word);break;case 3 :if(trie::search(word)){cout << "YES" << endl;}else{cout << "NO" << endl;}break;case 4 :cout << trie::prefixCount(word) <<endl;break;default:break;}
}

http://www.dtcms.com/a/310543.html

相关文章:

  • Rockchip RK3568J +FPGA边缘智能系统及储能网关
  • 以太网是什么网,什么网是以太网
  • spring cloud alibaba ——sidecar服务异构
  • Vite+React组件库提速方案
  • 区块链概述
  • 嵌入式 C 语言入门:函数封装与参数传递学习笔记 —— 从定义到内存机制
  • Syzkaller实战教程6:[重要]初始种子加载机制剖析第二集
  • 如何理解卷积,和自注意力机制的局限与优势(个人理解)
  • C++中typename基本用法
  • Nastool+cpolar:群晖NAS用户的全场景影音自由方案
  • 理解HTTP协议
  • 网络配置+初始服务器配置
  • Effective C++ 条款15:在资源管理类中提供对原始资源的访问
  • 在 Docker 中启动 Nginx 并挂载配置文件到宿主机目录
  • MyBatis知识点
  • 烽火HG680-KX-海思MV320芯片-2+8G-安卓9.0-强刷卡刷固件包
  • 电子电气架构 --- 加速48V技术应用的平衡之道
  • 机器学习sklearn:处理缺失值
  • 应用分层
  • 菜鸟教程Shell笔记 数组 运算符 echo命令
  • Qwen2 RotaryEmbedding 位置编码仅仅是第一层有吗
  • 深度学习-梯度爆炸与梯度消失
  • Node.js的用途和安装方法
  • flutter——ColorScheme
  • 第13届蓝桥杯Python青少组中/高级组选拔赛(STEMA)2021年10月24日真题
  • Class28批量归一化
  • java下载word
  • 第七章 愿景14 数据规划
  • 吃透 B + 树:MySQL 索引的底层逻辑与避坑指南
  • SpringMVC全局异常处理+拦截器使用+参数校验