【字典树】【字符串】【 前缀】100268. 最长公共后缀查询

作者推荐

视频算法专题

本文涉及知识点

字典树 字符串 前缀

LeetCode 100268. 最长公共后缀查询

给你两个字符串数组 wordsContainer 和 wordsQuery 。
对于每个 wordsQuery[i] ,你需要从 wordsContainer 中找到一个与 wordsQuery[i] 有 最长公共后缀 的字符串。如果 wordsContainer 中有两个或者更多字符串有最长公共后缀,那么答案为长度 最短 的。如果有超过两个字符串有 相同 最短长度,那么答案为它们在 wordsContainer 中出现 更早 的一个。
请你返回一个整数数组 ans ,其中 ans[i]是 wordsContainer中与 wordsQuery[i] 有 最长公共后缀 字符串的下标。
示例 1:
输入:wordsContainer = [“abcd”,“bcd”,“xbcd”], wordsQuery = [“cd”,“bcd”,“xyz”]
输出:[1,1,1]
解释:
我们分别来看每一个 wordsQuery[i] :
对于 wordsQuery[0] = “cd” ,wordsContainer 中有最长公共后缀 “cd” 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 1 的字符串,因为它的长度为 3 ,是最短的字符串。
对于 wordsQuery[1] = “bcd” ,wordsContainer 中有最长公共后缀 “bcd” 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 1 的字符串,因为它的长度为 3 ,是最短的字符串。
对于 wordsQuery[2] = “xyz” ,wordsContainer 中没有字符串跟它有公共后缀,所以最长公共后缀为 “” ,下标为 0 ,1 和 2 的字符串都得到这一公共后缀。这些字符串中, 答案是下标为 1 的字符串,因为它的长度为 3 ,是最短的字符串。
示例 2:
输入:wordsContainer = [“abcdefgh”,“poiuygh”,“ghghgh”], wordsQuery = [“gh”,“acbfgh”,“acbfegh”]
输出:[2,0,2]
解释:
我们分别来看每一个 wordsQuery[i] :
对于 wordsQuery[0] = “gh” ,wordsContainer 中有最长公共后缀 “gh” 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 2 的字符串,因为它的长度为 6 ,是最短的字符串。
对于 wordsQuery[1] = “acbfgh” ,只有下标为 0 的字符串有最长公共后缀 “fgh” 。所以尽管下标为 2 的字符串是最短的字符串,但答案是 0 。
对于 wordsQuery[2] = “acbfegh” ,wordsContainer 中有最长公共后缀 “gh” 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 2 的字符串,因为它的长度为 6 ,是最短的字符串。

提示:
1 <= wordsContainer.length, wordsQuery.length <= 104
1 <= wordsContainer[i].length <= 5 * 103
1 <= wordsQuery[i].length <= 5 * 103
wordsContainer[i] 只包含小写英文字母。
wordsQuery[i] 只包含小写英文字母。
wordsContainer[i].length 的和至多为 5 * 105
wordsQuery[i].length 的和至多为 5 * 105

字典树

将字符串全部反序,则后缀变成前缀。用字典树实现。
每个节点,包括根节点都要记录经过此节点的字符串的长度和下标。
内存超了的原因:
字典树的字符数最多是 5*105 每个字符 26种。合计:1.3e7, 接近内存超出的边缘。
将向量改成 哈希映射后,还是不行。
开始用set<pair<int,int>> 记录最小值,换成pair就可以了。

代码

template<class TData = char, int iTypeNum = 26, TData cBegin = 'a'>
class CTrieNodeEx
{
public:
	CTrieNodeEx* AddChar(TData ele)
	{
		const int index = ele - cBegin;
		if (!m_vPChilds.count(index))		
		{
			m_vPChilds[index] = new CTrieNodeEx();
		}
		return m_vPChilds[index];
	}
	CTrieNodeEx* GetChild(TData ele)
	{
		const int index = ele - cBegin;
		if (m_vPChilds.count(index))
		{
			return m_vPChilds[index];
		}
		return nullptr;
	}
public:
	pair<int, int> m_lenIndex = { 1000'1000,0 };
protected:
	unordered_map<int, CTrieNodeEx*> m_vPChilds;
};


template<class TData = char, int iTypeNum = 26, TData cBegin = 'a'>
class CTrieEx
{
public:	
	void Add(const string& str,int index)
	{
		auto lenIndex = std::make_pair((int)str.length(),index);
		auto pNode = &m_root;
		if (lenIndex < pNode->m_lenIndex)
		{
			pNode->m_lenIndex = lenIndex;
		}
		for (const auto& ch : str )
		{
			pNode = pNode->AddChar(ch);
			if (lenIndex < pNode->m_lenIndex)
			{
				pNode->m_lenIndex = lenIndex;
			}
		}
	}
	int Find(const string& str)
	{
		auto pNode = &m_root;
		for (const auto& ch : str)
		{
			auto tmp = pNode->GetChild(ch);
			if (nullptr == tmp)
			{
				break;
			}
			pNode = tmp;
		}
		return pNode->m_lenIndex.second;
	}
	CTrieNodeEx<TData, iTypeNum, cBegin> m_root;	
};

class Solution {
public:
	vector<int> stringIndices(vector<string>& wordsContainer, vector<string>& wordsQuery) {
		CTrieEx trie;
		for (int i = 0; i < wordsContainer.size(); i++)
		{
			string strRev(wordsContainer[i].rbegin(), wordsContainer[i].rend());
			trie.Add(strRev, i);
		}
		vector<int> vRet;
		for (int i = 0; i < wordsQuery.size(); i++)
		{
			string strRev(wordsQuery[i].rbegin(), wordsQuery[i].rend());
			vRet.emplace_back(trie.Find(strRev));
		}
		return vRet;
	}
};

测试用例

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

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]);
	}

}

int main()
{
	vector<string> wordsContainer, wordsQuery;
	{
		Solution sln;
		wordsContainer = { "abcd", "bcd", "xbcd" }, wordsQuery = { "cd", "bcd", "xyz" };
		auto res = sln.stringIndices(wordsContainer, wordsQuery);
		Assert({ 1,1,1 }, res);
	}
	{
		Solution sln;
		wordsContainer = { "abcdefgh", "poiuygh", "ghghgh" }, wordsQuery = { "gh", "acbfgh", "acbfegh" };
		auto res = sln.stringIndices(wordsContainer, wordsQuery);
		Assert({ 2,0,2 }, 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++**实现。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux课程_____网络管理

一、查看接口信息 1. ifconfig 查看所有活动网络接口的信息 ifconfig -a 查看所有网络接口信息 ifconfig 直接加网络接口 查看指定网络接口信息 1.1查看指定接口IP [rootlocalhost ~]# ip addr show ens160 1.2设置网络接口的IP地址 # ifconfig eth0 192.168.152.133 …

基于Springboot+Vue的前后端分离的简单Demo案例(二)

前端搭建 Vue router 来动态构建左侧菜单 导航1 页面1页面2导航2 页面3页面4导航3 页面5页面6 在views目录下创建四个页面 PageOne.vue <template><h1>这是页面1</h1> </template> <script> export default {name: "PageOne", }; …

Java String类深入了解JDK各个版本进阶版本

Java String类深入了解JDK各个版本进阶版本 一&#xff0c;底层类型 在jdk11中 String value 存储字符串值 是byte[] 数组 &#xff0c;String中存储字节码的是coder 也是byte类型&#xff0c;因此String的底层数据存储类型成为了byte类型 而在jdk8中String 的String value 存…

shell编程-jq命令详解

文章目录 前言一、jq简介1. 简介2. 语法3. 命令选项 二、用于处理json数据1. 过滤1.1 标识运算符1.2 基本过滤1.3 获取对象属性1.3 迭代数组元素1.4 获取数组元素1.5 使用运算符 2. 类型和值2.1 数组构造2.2 对象构造2.3 递归下降 3. 内置运算符和函数3.1 算术运算符3.2 函数3.…

Makefile的override

今天在编译opengauss extension时遇到一个报错&#xff1a; 简单的理解就是编译时要加 -fPIC&#xff0c;告诉编译器生成Position Independent Code&#xff0c;试过 make CPPFLAGS-fPIC 可以成功编译&#xff0c;不过看到其它的解决方案是在Makefile中加 override CPPFLAG…

代码随想录算法训练营第三十天 | 332.重新安排行程,51. N皇后 ,37. 解数独

这道题是一道欧拉路径/ 欧拉回路的一笔画问题&#xff0c;需要找出开销最小的一笔画方案 这种一笔画的问题&#xff0c;以前学数据结构的时候我们习惯把图放进二维数组中存储&#xff0c;但对于这种无规律的图结构&#xff0c;我们可以使用二维的哈希表来存储&#xff0c;这样…

【4月】CDA Club 第2期数据分析组队打卡学习活动开启!

活动名称 CDA Club 第2期数据分析组队打卡学习活动 活动介绍 本次打卡活动由CDA俱乐部旗下学术部主办。目的是通过数据分析科普内容&#xff0c;为数据分析爱好者提供学习和交流的机会。方便大家利用碎片化时间在线学习&#xff0c;以组队打卡的形式提升学习效果&#xff0c…

水离子雾化壁炉的原理和技术解析

水离子雾化壁炉采用超声波雾化技术将水分子雾化成微细的水离子&#xff0c;然后通过风扇吹出再经过UVC紫外线杀菌产生安全仿真的火焰效果。以下是水离子雾化壁炉的原理和技术解析&#xff1a; 超声波雾化技术&#xff1a; 水离子雾化壁炉利用超声波振动器产生高频振动&#xf…

[Java、Android面试]_13_map、set和list的区别

本人今年参加了很多面试&#xff0c;也有幸拿到了一些大厂的offer&#xff0c;整理了众多面试资料&#xff0c;后续还会分享众多面试资料。 整理成了面试系列&#xff0c;由于时间有限&#xff0c;每天整理一点&#xff0c;后续会陆续分享出来&#xff0c;感兴趣的朋友可关注收…

TSN协议原理!看完这一篇就够了(1)——时钟同步IEEE802.1AS-2020

▎前言 在许多应用场景中&#xff0c;一个本地局域网中互联的设备集群需要共享同一个时间&#xff0c;以支持各设备的协同工作。例如&#xff1a;音频设备与视频设备的配合播放&#xff0c;雷达与摄像头的数据融合等&#xff1b;这样一个看似简单的域功能&#xff0c;细化成为…

好书推荐 :《 提问的艺术:让 ChatGPT 给出高质量答案 》

AGI 时代降临&#xff01;还不知如何向 ChatGPT 提问&#xff1f; 恰当的提示至关重要&#xff01;《提问的艺术—让 ChatGPT 给出高质量答案》一书&#xff0c;共 24 章&#xff0c;系统介绍了如何向 ChatGPT 提问以获取优质答案&#xff0c;是 ChatGPT 时代的入门指南&#x…

【 Mysql8.0 忘记登录密码 可以试试 】

** Mysql8.0 忘记登录密码 可以试试 ** 2024-3-21 段子手168 1、首先停止 mysql 服务 &#xff0c;WIN R 打开运行&#xff0c;输入 services.msc 回车打开服务&#xff0c;找到 mysql 服务&#xff0c;停止。 然后 WIN R 打开运行&#xff0c;输入 CMD 打开控制台终端输…

‘npm‘ 不是内部或外部命令,也不是可运行的程序

npm认识三年了&#xff0c;今天才知道这是node.js的命令 也就是说&#xff0c;想要在cmd里面运行 npm 命令&#xff0c;但就的安装node.js 1. node.js安装 没有安装包的先下载安装包&#xff1a;下载 | Node.js 中文网 (nodejs.cn) 下载之后双击打开&#xff0c;一路安装确…

如何为企业策划一场XR虚拟直播?

活动年年办&#xff0c;都是老一套&#xff0c;想玩点新花样&#xff1f; 预算有限&#xff0c;但还是想把活动办的逼格高一点&#xff1f; 想通过活动&#xff0c;让更多的人知道自己企业的品牌&#xff1f; 随着AIGC技术的不断演变&#xff0c;企业活动的形式和内容也在不…

Node.js之沙盒专题

​ Node.js一直是薄弱项&#xff0c;今天特意整理一下&#xff0c;基本上是各个大佬写的大杂烩&#xff0c;仅用于学习记录~~~ 1. child_process 首先介绍一下nodejs中用来执行系统命令的模块child_process。Nodejs通过使用child_process模块来生成多个子进程来处理其他事物…

滤波器自动化测试:用网络分析仪、示波器、功率计测量功率

滤波器的功率是电压与电流的乘积&#xff0c;滤波器的功率可以通过测量电压与电流计算得出。滤波器的功率对滤波器的稳定运行是至关重要的&#xff0c;如果功率过小可能会导致滤波器无法正常工作;功率越大则有可能会造成滤波器的损坏。因此滤波器的功率测量是非常重要的步骤。 …

基于51单片机的客车汽车安全气囊控制器Proteus仿真

地址&#xff1a;https://pan.baidu.com/s/10enj1EYm_0Z8f_19Sz_eCQ 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52简介&#xff1a; AT89C52是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectronics&#xff09;公…

第一周周考技能

文章目录 1月1. 任意输入一个3位整数&#xff08;100~999&#xff0c;包含100与999&#xff09;&#xff0c;判断输入的整数是否是质数&#xff0c;如果是质数则输出是质数&#xff0c;否则输出不是质数2.“降序数”是指一个自然数的低位数字不大于高位数字的数。例如&#xff…

工单系统大揭秘!选择工单系统需注意的关键因素!

如何选择工单系统&#xff1f;工单系统作为数字化工具&#xff0c;可以帮助企业高效处理工单业务问题&#xff0c;助力企业数字化转型。目前市面上的工单系统可谓是琳琅满目。 本文详细讲解了目前市面上工单系统的主要类型&#xff0c;以及企业该如何选择工单系统~ 一、工单系…

怎样批量在文件名后面加上相同的字符?

怎样批量在文件名后面加上相同的字符&#xff1f;在日常工作中&#xff0c;有时我们需要对大量文件进行批量处理&#xff0c;比如在文件名后面统一添加相同的字符。这项工作可以通过编写简单的脚本或程序来实现&#xff0c;从而提高工作效率。批量在文件名后面加上相同的字符是…