676.实现一个魔法字典·前缀树
链接:https://leetcode.cn/problems/implement-magic-dictionary/solution/by-xun-ge-v-3c60/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题目
示例
思路
本题为前缀树和dfs的一个结合
求解字符串s(searchWord)在另外一个字典集d(dictionary)中相关操作都可以运用
前缀树https://leetcode.cn/problems/implement-trie-prefix-tree/solution/chun-c-by-xun-ge-v-vnt5/
进行优化,力扣也有关于前缀树实现的习题,对前缀树不了解的可以进链接
前缀树:前缀树是一种用于快速检索的多叉树结构,利用字符串的公共前缀来降低查询时间,核心思想是空间换时间,经常被搜索引擎用于文本词频统计。
typedef struct MagicDictionary{
bool logo;//true表示字符串结束,false表示字符未结束
struct MagicDictionary * next[26];
} MagicDictionary;
其中前缀树中每一个节点代表一个字符,以一个节点进行深度优先搜索,一直到末尾,那么经过的路径就为字典集中的一个字符串
具体实现
先对字典集d进行优化,转换为对应的前缀树,将所有的d子串存入字典树中,方便后续检索;
设计递归函数dfs(MagicDictionary * obj, char * searchWord, int inode, int len, int x),searchWord其中为待检索的字符串,inode为当前处理到字符串 s 的哪一位,obj为当前搜索到字典树的索引编号,x为当前剩余的替换字符次数,根据题意,x固定为 1,含义为必须替换掉 s 的一个字符。
对于s而言,我们可以枚举新字符串在当前位置是何种字符(i = 26个选择),若当前枚举到的字符与 s[inode] 一致,则不消耗替换次数。
递归过程中替换次数为负数直接剪枝,当递归到字符串s结尾位置,检查是否位于前缀树末尾,并且x为0
代码
//前缀树 + 递归 + 深度优先搜索
typedef struct MagicDictionary{bool logo;//true表示字符串结束,false表示字符未结束struct MagicDictionary * next[26];
} MagicDictionary; //初始化
MagicDictionary* magicDictionaryCreate() {MagicDictionary * obj = malloc(sizeof(MagicDictionary));for(int i = 0; i < 26; i++){obj->next[i] = NULL;}obj->logo = false;return obj;
}
//转换前缀树
void magicDictionaryBuildDict(MagicDictionary* obj, char ** dictionary, int dictionarySize) {if(dictionarySize > 1){magicDictionaryBuildDict(obj, dictionary, dictionarySize - 1);}int len = strlen(dictionary[dictionarySize-1]);for(int i = 0; i < len; i++){if(obj->next[dictionary[dictionarySize-1][i] - 'a'] == NULL){MagicDictionary * n = magicDictionaryCreate();obj->next[dictionary[dictionarySize-1][i] - 'a'] = n;}obj = obj->next[dictionary[dictionarySize-1][i] - 'a'];}obj->logo = true;
}
//递归判断字符串在字典树的情况
bool dfs(MagicDictionary * obj, char * searchWord, int inode, int len, int x)
{if(x < 0)//剪枝{return false;}if(inode == len)//到字符串末尾了,判断一下是否换了一个字符,是不是在字典集中存在完整的字符串{if(x == 0 && obj->logo == true){return true;}else{return false;}}for(int i = 0; i < 26; i++)//寻找同层前缀树中存在的元素{if(obj->next[i])//存在{if(i == (searchWord[inode] - 'a'))//是不是和目标元素一样{if(dfs(obj->next[i], searchWord, inode+1, len, x) == true){return true;}} else//不一样,修改次数-1,继续{if(dfs(obj->next[i], searchWord, inode+1, len, x-1) == true){return true;}}}}return false;//前缀树遍历完了,没有字符串和s字符串匹配
}//调用dfs函数深度优先搜索
bool magicDictionarySearch(MagicDictionary* obj, char * searchWord) {int len = strlen(searchWord);return dfs(obj, searchWord, 0, len, 1);
}
//销毁前缀树
void magicDictionaryFree(MagicDictionary* obj) {for(int i = 0; i < 26; i++){if(obj->next[i]){magicDictionaryFree(obj->next[i]); }}free(obj);
}/*** Your MagicDictionary struct will be instantiated and called as such:* MagicDictionary* obj = magicDictionaryCreate();* magicDictionaryBuildDict(obj, dictionary, dictionarySize);* bool param_2 = magicDictionarySearch(obj, searchWord);* magicDictionaryFree(obj);
*/
时间空间复杂度
676.实现一个魔法字典·前缀树相关推荐
- LeetCode 676. 实现一个魔法字典
文章目录 一.题目 1.题目描述 2.基础框架 3.原题链接 二.解题报告 1.思路分析 2.时间复杂度 3.代码详解 三.本题小知识 四.加群须知 一.题目 1.题目描述 设计一个使用单词列表进 ...
- 676. 实现一个魔法字典
676. 实现一个魔法字典 设计一个使用单词列表进行初始化的数据结构,单词列表中的单词 互不相同 . 如果给出一个单词,请判定能否只将这个单词中一个字母换成另一个字母,使得所形成的新单词存在于你构建的 ...
- leetcode 676. Implement Magic Dictionary | 676. 实现一个魔法字典(DFS+Trie 前缀树)
题目 https://leetcode.com/problems/implement-magic-dictionary/description/ 题解 题意理解 前缀树问题,大意是是让你在字典中找到是 ...
- LeetCode 676. 实现一个魔法字典(哈希)
1. 题目 实现一个带有buildDict, 以及 search方法的魔法字典. 对于buildDict方法,你将被给定一串不重复的单词来构建一个字典. 对于search方法,你将被给定一个单词,并且 ...
- trie(字典树、前缀树)
trie(字典树.前缀树) 1. trie原理 原理 trie树,又被称为字典树.前缀树,是一种高效地存储和查找字符串集合的数据结构. 一般来说,用到trie的题目中的字母要么全是小写字母,要么全是大 ...
- 树结构-------前缀树
何为前缀树:又叫字典树.单词查找树或键树,是一种多叉树结构.如下图 上图是一棵Trie树,表示了关键字集合{"a", "to", "tea" ...
- 前缀树(Trie)原理及Java实现
前缀树的结构 Trie树,又叫字典树.前缀树(Prefix Tree).单词查找树或键树,是一种多叉树结构.如下图: 上图是一棵Trie树,表示了关键字集合{"a", " ...
- Trie(前缀树/字典树)及其应用
from:https://www.cnblogs.com/justinh/p/7716421.html Trie,又经常叫前缀树,字典树等等.它有很多变种,如后缀树,Radix Tree/Trie,P ...
- 字典数(前缀树)的实现
[题目] 字典树又称为前缀树或者Trie树,是处理字符串常用的数据结构.假设组成所有单词的字符仅是'a'-'z',请实现字典树的结构,并包含以下四个主要的功能. void insert(String ...
最新文章
- 提升玩家游戏体验与账户安全,是游戏行业网络方案是重中之重
- java 线程一直运行状态_详解JAVA 线程-线程的状态有哪些?它是如何工作的?
- 多线程程序中操作的原子性
- linux shell 脚本实现:根据文件内容中的每行分隔符放入数组,根据规则打印日志并重新创建目录 备份文件
- C#字典转换成where条件
- 一幅图告诉你C-C++注释转换有多简单
- linux命令大全密码修改,linux修改密码命令
- mac 壁纸 android,Mac系统风格桌面
- 了解Linux操作系统
- 人脸识别技术全面总结
- rainyday.js 下雨效果插件使用方法
- 主干开发(Trunk-based development)
- 华为云主机安全防护的新发现
- 2020年最好用的手机是哪一款_2020年公认最值得入手的3款手机,颜值性能兼具,用三年不亏!...
- 软件测试面试-为什么选择软件测试?
- 二分查找算法(随机, 最左, 最右)
- 聊一聊回收科技那些事儿
- ImageMagick windows下的安装和gif动图制作
- 微信小程序Ⅴ [获取登录用户信息,重点openID(详解)]
- Mac电脑投屏到Linux,苹果电脑投屏到显示器的三种常见方式
热门文章
- SharePoint 2010 安装错误:请重新启动计算机,然后运行安装程序以继续
- c语言简单小游戏(模拟魔塔)
- Django个人博客搭建教程---用Vue写你的第一个前后端分离页面
- 【算法】哈夫曼压缩算法-学习记录
- 在Oracle中采用纵向和横向结构表
- lottie android 源码,Lottie动画库 Android 端源码浅析
- 戴戴戴师兄-数据分析课程笔记(第二讲)
- php mysql text换行符_请教php配合mysql的换行符和空格字符问题
- linux网口初始化_Linux 初始化系统配置(CentOS 6)
- 数据结构(C语言第2版) 课后习题答案之第五章 树和二叉树