【字典树(前缀树) 字符串】2416. 字符串的前缀分数和

news2024/11/16 21:57:29

本文涉及知识点

字典树(前缀树) 字符串

LeetCode 2416. 字符串的前缀分数和

给你一个长度为 n 的数组 words ,该数组由 非空 字符串组成。
定义字符串 word 的 分数 等于以 word 作为 前缀 的 words[i] 的数目。
例如,如果 words = [“a”, “ab”, “abc”, “cab”] ,那么 “ab” 的分数是 2 ,因为 “ab” 是 “ab” 和 “abc” 的一个前缀。
返回一个长度为 n 的数组 answer ,其中 answer[i] 是 words[i] 的每个非空前缀的分数 总和 。
注意:字符串视作它自身的一个前缀。

示例 1:
输入:words = [“abc”,“ab”,“bc”,“b”]
输出:[5,4,3,2]
解释:对应每个字符串的答案如下:

  • “abc” 有 3 个前缀:“a”、“ab” 和 “abc” 。
  • 2 个字符串的前缀为 “a” ,2 个字符串的前缀为 “ab” ,1 个字符串的前缀为 “abc” 。
    总计 answer[0] = 2 + 2 + 1 = 5 。
  • “ab” 有 2 个前缀:“a” 和 “ab” 。
  • 2 个字符串的前缀为 “a” ,2 个字符串的前缀为 “ab” 。
    总计 answer[1] = 2 + 2 = 4 。
  • “bc” 有 2 个前缀:“b” 和 “bc” 。
  • 2 个字符串的前缀为 “b” ,1 个字符串的前缀为 “bc” 。
    总计 answer[2] = 2 + 1 = 3 。
  • “b” 有 1 个前缀:“b”。
  • 2 个字符串的前缀为 “b” 。
    总计 answer[3] = 2 。
    示例 2:

输入:words = [“abcd”]
输出:[4]
解释:
“abcd” 有 4 个前缀 “a”、“ab”、“abc” 和 “abcd”。
每个前缀的分数都是 1 ,总计 answer[0] = 1 + 1 + 1 + 1 = 4 。

提示:

1 <= words.length <= 1000
1 <= words[i].length <= 1000
words[i] 由小写英文字母组成

字典树

字典树各节点记录子树数量。
针对每个word ,一次查询word[0…j] 子孙的数量,累加就可以了。

代码

核心代码

namespace NTmp {
	template<class TData = char, int iTypeNum = 26, TData cBegin = 'a'>
	class CTrieNode
	{
	public:
		~CTrieNode()
		{
			for (auto& [tmp, ptr] : m_dataToChilds) {
				delete ptr;
			}
		}
		CTrieNode* AddChar(TData ele, int& iMaxID)
		{
#ifdef _DEBUG
			if ((ele < cBegin) || (ele >= cBegin + iTypeNum))
			{
				return nullptr;
			}
#endif
			const int index = ele - cBegin;
			auto ptr = m_dataToChilds[ele - cBegin];
			if (!ptr)
			{
				m_dataToChilds[index] = new CTrieNode();
#ifdef _DEBUG
				m_dataToChilds[index]->m_iID = ++iMaxID;
				m_childForDebug[ele] = m_dataToChilds[index];
#endif
			}
			m_dataToChilds[index]->m_iChildChildCount++;
			return m_dataToChilds[index];
		}
		CTrieNode* GetChild(TData ele)
		{
#ifdef _DEBUG
			if ((ele < cBegin) || (ele >= cBegin + iTypeNum))
			{
				return nullptr;
			}
#endif
			return m_dataToChilds[ele - cBegin];
		}
	protected:
#ifdef _DEBUG
		int m_iID = -1;
		std::unordered_map<TData, CTrieNode*> m_childForDebug;
#endif
	public:
		int m_iLeafIndex = -1;
		int m_iChildChildCount = 0;
	protected:
		//CTrieNode* m_dataToChilds[iTypeNum] = { nullptr };//空间换时间 大约216字节
		//unordered_map<int, CTrieNode*>    m_dataToChilds;//时间换空间 大约56字节
		map<int, CTrieNode*>    m_dataToChilds;//时间换空间,空间略优于哈希映射,数量小于256时,时间也优。大约48字节
	};
	template<class TData = char, int iTypeNum = 26, TData cBegin = 'a'>
	class CTrie
	{
	public:
		int GetLeadCount()
		{
			return m_iLeafCount;
		}
		CTrieNode<TData, iTypeNum, cBegin>* AddA(CTrieNode<TData, iTypeNum, cBegin>* par, TData curValue)
		{
			auto curNode = par->AddChar(curValue, m_iMaxID);
			FreshLeafIndex(curNode);
			return curNode;
		}
		template<class IT>
		int Add(IT begin, IT end)
		{
			auto pNode = &m_root;
			for (; begin != end; ++begin)
			{
				pNode = pNode->AddChar(*begin, m_iMaxID);
			}
			FreshLeafIndex(pNode);
			return pNode->m_iLeafIndex;
		}
		template<class IT>
		CTrieNode<TData, iTypeNum, cBegin>* Search(IT begin, IT end)
		{
			auto ptr = &m_root;
			for (; begin != end; ++begin)
			{
				ptr = ptr->GetChild(*begin);
				if (nullptr == ptr)
				{
					return nullptr;
				}
			}
			return ptr;
		}
		CTrieNode<TData, iTypeNum, cBegin> m_root;
	protected:
		void FreshLeafIndex(CTrieNode<TData, iTypeNum, cBegin>* pNode)
		{
			if (-1 == pNode->m_iLeafIndex)
			{
				pNode->m_iLeafIndex = m_iLeafCount++;
			}
		}
		int m_iMaxID = 0;
		int m_iLeafCount = 0;
	};

}
class Solution {
public:
	vector<int> sumPrefixScores(vector<string>& words) {
		NTmp::CTrie<> trie;
		for (const auto& s: words) {
			trie.Add(s.begin(), s.end());
		}
		vector<int> vRet;
		for (const auto& s : words) {
			auto ptr = &trie.m_root;
			int cnt = 0;
			for (const auto& ch : s) {
				ptr = ptr->GetChild(ch);
				cnt += ptr->m_iChildChildCount;
			}
			vRet.emplace_back(cnt);
		}
		return vRet;
	}
};

测试用例

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		assert(v1[i] == v2[i]);
	}
}

template<class T>
void Assert(const T& t1, const T& t2)
{
	assert(t1 == t2);
}

int main()
{
	vector<string> words;
	{
		Solution slu;
		words = { "abc", "ab", "bc", "b" };
		auto res = slu.sumPrefixScores(words);
		Assert({ 5,4,3,2 }, res);
	}
	{
		Solution slu;
		words = {"abcd" };
		auto res = slu.sumPrefixScores(words);
		Assert({ 4 }, res);
	}
}

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1700581.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【NOIP2015普及组复赛】题3:求和

题3&#xff1a;求和 【题目描述】 一条狭长的纸带被均匀划分出了 n n n 个格子&#xff0c;格子编号从 1 1 1 到 n n n。每个格子上都染了一种颜色 c o l o r i color_i colori​ &#xff08;用 [ 1 &#xff0c; m ] [1&#xff0c;m] [1&#xff0c;m]当中的一个整数表…

【数据结构】排序算法大全(快速、堆、归并、插入、折半、希尔、冒泡、计数、基数)各算法比较、解析+完整代码

文章目录 八、排序1.插入排序1.1 直接插入排序1.2 折半插入排序1.3 希尔排序 2.交换排序2.1 冒泡排序2.2 快速排序 3.选择排序3.1 简单选择排序3.2 堆3.2.1 堆排序3.2.2 堆插入删除*完善代码 堆 4.归并、基数、计数排序4.1 归并排序4.2 基数排序4.3 计数排序 5.内部排序算法的比…

JAVA:Spring Boot整合MyBatis Plus持久层

1、简述 MyBatis Plus是MyBatis的增强工具包&#xff0c;它在MyBatis的基础上进行了扩展&#xff0c;提供了许多便捷的功能&#xff0c;例如通用CRUD操作、分页插件、代码生成器等。使用MyBatis Plus&#xff0c;开发者可以更加方便地进行持久层操作&#xff0c;并且减少了很多…

Python爬虫实战:利用代理IP获取电商数据

文章目录 1.电商数据介绍2.爬取目标3.代理IP推荐4.准备工作4.1 模块安装4.2 代理IP获取 5.爬虫代码实战5.1分析网页5.1.1 获取cookie5.1.2 关键词分析5.1.3 翻页分析5.1.4 数据获取分析 5.2 发送请求5.3 提取数据5.4 保存数据5.5 完整源码5.6 数据分析六、总结 1.电商数据介绍 …

[随笔] 在CSDN的6周年纪念日随笔

纪念 转眼已过6年&#xff0c;大一的时候学习编程&#xff0c;潜水 CSDN 学习各类博文&#xff0c;才学浅薄就没有主动写博文记录自己的学习历程。 过了段时间刚刚到了大二&#xff0c;很喜欢 Todolist&#xff0c;意气风发的写下《一份清爽的编程计划》&#xff0c;哈哈。 …

冷冻式压缩空气干燥机常见几种系统原理图

冷冻式压缩空气干燥机 我们以两种典型的设计流程图为例 1.干式蒸发型&#xff0c;这类冷干机是我们最为常见的设计型式。下图为deltech公司的典型流程图 此类设备各家设计不同的最大区别基本就是在换热器的结构型式上有比较大的区别。换热器主要有&#xff1a;管壳式、铝板换、…

【openlayers系统学习】00官网的Workshop介绍

00Workshop介绍 官方文档&#xff1a;https://openlayers.org/workshop/en/ openlayers官网Workshop学习。 通过官网Workshop&#xff0c;系统学习openlayers的使用。 基本设置 这些说明假定您从最新Workshop版本的 openlayers-workshop-en.zip​ 文件开始。此外&#xff…

KingbaseES数据库merge语法

数据库版本&#xff1a;KingbaseES V008R006C008B0014 简介 MERGE 语句是一种用于数据操作的 SQL 语句&#xff0c;它能够根据指定的条件将 INSERT、UPDATE 和 DELETE 操作结合到单个语句中。其主要作用是在目标表和源表之间进行数据比较和同步&#xff0c;根据条件的匹配情况来…

IBERT眼图扫描(高速收发器八)

前文讲解了GTX的时钟及收发数据通道的组成&#xff0c;之后讲解了眼图、加重、均衡等原理及原因&#xff0c;本文通过xilinx提供的IBERT IP完成实际工程的眼图扫描&#xff0c;确定加重和幅值调节的参数。 1、回环模式 在此之前&#xff0c;需要了解一下GTX的回环模式。如果板…

批处理作业调度问题 (回溯法)

目录 一、问题解析 二、实例剖析 三、算法思路 四、代码实现 结果&#xff1a; 总结 前言 【问题】n 个作业{1, 2, …, n}要在两台机器上处理&#xff0c;每个作业必须先由机器 1 处理&#xff0c;再由机器 2 处理&#xff0c;机器 1 处理作业i所需时间为 ai&#xff0c;…

【Unity实战篇 】| Unity实现 文本框可以自适应大小,到达最大宽度之后再缩小字体

前言 在文本框可以自适应大小拉伸的前提下,增加一个最大限制宽度,使其到达最大宽度后 再启用 Best Fit 实现自适应改变文字大小以适应文本框的大小。 【Unity实战篇 】 | Unity实现 Text文本框可以自适应大小,到达最大宽度之后再缩小字体 在Unity中经常会用到文本组件的自…

Jmeter插件下载(下载和使用教程)

插件管理器&#xff1a;plugins-manager下载安装和使用 下载&#xff1a; 官网地址&#xff1a;https://jmeter-plugins.org/install/Install/ 步骤1&#xff1a;将下载jmeter-plugins-manager-1.10.jar放到目录apache-jmeter-5.1.1\lib\ext&#xff0c;如下图 步骤2&#x…

《最新出炉》系列入门篇-Python+Playwright自动化测试-42-强大的可视化追踪利器Trace Viewer

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 在我们日常执行自动化测试工作的过程中&#xff0c;经常会遇到一些偶发性的bug&#xff0c;但是因为bug是偶发性的&#xff0c;我们不一定每次执行都能复现&#xff0c;所以我…

力扣刷题--747. 至少是其他数字两倍的最大数【简单】

题目描述 给你一个整数数组 nums &#xff0c;其中总是存在 唯一的 一个最大整数 。 请你找出数组中的最大元素并检查它是否 至少是数组中每个其他数字的两倍 。如果是&#xff0c;则返回 最大元素的下标 &#xff0c;否则返回 -1 。 示例 1&#xff1a; 输入&#xff1a;n…

Android端 可使用Yolov5训练 路标识别

相信大家对于路标识别&#xff0c;红绿灯识别&#xff0c;图形识别opencv中也是一件烦人的事情&#xff0c;其参数是及其受到现实环境因素的影响的&#xff0c;那么今天我就给大家推荐一种方式&#xff0c;缺点是周期长&#xff0c;但其优点是如果训练效果好久对于环境的各种变…

河南乙级道路与桥梁资质年审材料准备要点解析

河南乙级道路与桥梁资质年审材料准备要点解析如下&#xff1a;河南宽信权经理 一、企业基本情况材料 营业执照副本复印件&#xff1a;确保复印件清晰、完整&#xff0c;并加盖企业公章。 企业章程&#xff1a;提供最新的企业章程&#xff0c;并加盖企业公章。此材料需反映企业…

matepad11和matepad2023区别

​ 华为MatePad11和MatePad2023是华为公司推出的两款平板电脑&#xff0c;它们在处理器、价格和屏幕等方面存在差异。具体分析如下&#xff1a; 处理器 MatePad 11英寸2023款&#xff1a;搭载骁龙865处理器&#xff0c;最高主频为2.84GHz。 MatePad 2023&#xff1a;配备骁…

Android:使用Kotlin搭建MVVM+组件化App架构

一、简介Android MVVM架构模式 请点击查看Android&#xff1a;使用Kotlin搭建MVVM架构模式 二、简介组件化 以前一个项目所有业务代码都在App&#xff08;model&#xff09;里开发&#xff0c;App里按照功能模块分包&#xff0c;例如&#xff1a;首页&#xff08;home&#xff…

58同城前端社招一面挂了,面试总结:coding能力有待提高

总结面试不足&#xff1a;coding能力有待提高&#xff0c;项目对于大厂面试来说不够有亮点&#xff0c;难度不够&#xff0c;对于技术细节不够深入。下周继续加油&#xff0c;噢力给给&#xff01;&#xff01;&#xff01;&#x1f62d;&#x1f62d;&#x1f62d; 面试题 1、…

[Algorihm][简单多状态DP问题][买卖股票的最佳时机含冷冻期][买卖股票的最佳时机含手续费]详细讲解

目录 1.买卖股票的最佳时机含冷冻期1.题目链接买卖股票的最佳时机含冷冻期2.算法原理详解3.代码实现 2.买卖股票的最佳时机含手续费1.题目链接2.算法原理详解3.代码实现 1.买卖股票的最佳时机含冷冻期 1.题目链接 买卖股票的最佳时机含冷冻期 2.算法原理详解 思路&#xff…