【解析几何】 【多源路径】 【贪心】1520 最多的不重叠子字符串

作者推荐

视频算法专题

本身涉及知识点

解析几何 图论 多源路径 贪心

LeetCode1520. 最多的不重叠子字符串

给你一个只包含小写字母的字符串 s ,你需要找到 s 中最多数目的非空子字符串,满足如下条件:
这些字符串之间互不重叠,也就是说对于任意两个子字符串 s[i…j] 和 s[x…y] ,要么 j < x 要么 i > y 。
如果一个子字符串包含字符 char ,那么 s 中所有 char 字符都应该在这个子字符串中。
请你找到满足上述条件的最多子字符串数目。如果有多个解法有相同的子字符串数目,请返回这些子字符串总长度最小的一个解。可以证明最小总长度解是唯一的。
请注意,你可以以 任意 顺序返回最优解的子字符串。
示例 1:
输入:s = “adefaddaccc”
输出:[“e”,“f”,“ccc”]
解释:下面为所有满足第二个条件的子字符串:
[
“adefaddaccc”
“adefadda”,
“ef”,
“e”,
“f”,
“ccc”,
]
如果我们选择第一个字符串,那么我们无法再选择其他任何字符串,所以答案为 1 。如果我们选择 “adefadda” ,剩下子字符串中我们只可以选择 “ccc” ,它是唯一不重叠的子字符串,所以答案为 2 。同时我们可以发现,选择 “ef” 不是最优的,因为它可以被拆分成 2 个子字符串。所以最优解是选择 [“e”,“f”,“ccc”] ,答案为 3 。不存在别的相同数目子字符串解。
示例 2:
输入:s = “abbaccd”
输出:[“d”,“bb”,“cc”]
解释:注意到解 [“d”,“abba”,“cc”] 答案也为 3 ,但它不是最优解,因为它的总长度更长。
提示:
1 <= s.length <= 105
s 只包含小写英文字母。

分析

{ 如果一个子字符串包含字符 c h a r ,那么 s 中所有 c h a r 字符都应该在这个子字符串中。简称条件一。 子串(非子序列 ) 如果某个子串包括 c 1 ,则包括所有 c 1 和之间所有字符。 \begin{cases} 如果一个子字符串包含字符 char ,那么 s 中所有 char 字符都应该在这个子字符串中。 简称条件一。\\ 子串(非子序列)\\ \end{cases} 如果某个子串包括c1,则包括所有c1和之间所有字符。 {如果一个子字符串包含字符char,那么s中所有char字符都应该在这个子字符串中。简称条件一。子串(非子序列)如果某个子串包括c1,则包括所有c1和之间所有字符。

多源路径

26个字符看成26个节点,如果字符c1之间有字符c2,则有有向边 c 1 c 2 → \overrightarrow{c1c2} c1c2 。利用多源路径看c1到c3是否存在,如果存在则选择c1时,c3也必须选择。令选择c1后,至少选择[l1,r1]。

解析几何

把[i1,r1]看线段,求最多不相交的线段。

贪心

第一条线段,一定是ri最小的,令为t1,显然越小,第二条线越容易找。
第二条线段,一定是ri最小,且li大于t1的。
⋮ \vdots

线段不会交叉,只能包括或相离。所以ri小的,就短。
令a<b<c<d,假定线段:ac和bd相交与bc。
ab中一定有bc中的某个字符,假定其小标为i1,否则ac不会包括bc。bd包括bc,故有此字符,bd必须包括i1,与假设矛盾。

代码

核心代码

//多源码路径
template<class T, T INF = 1000 * 1000 * 1000>
class CFloyd
{
public:
	CFloyd(const  vector<vector<T>>& mat)
	{
		m_vMat = mat;
		const int n = mat.size();
		for (int i = 0; i < n; i++)
		{//通过i中转
			for (int i1 = 0; i1 < n; i1++)
			{
				for (int i2 = 0; i2 < n; i2++)
				{
					//此时:m_vMat[i1][i2] 表示通过[0,i)中转的最短距离
					m_vMat[i1][i2] = min(m_vMat[i1][i2], m_vMat[i1][i] + m_vMat[i][i2]);
					//m_vMat[i1][i2] 表示通过[0,i]中转的最短距离
				}
			}
		}
	};
	vector<vector<T>> m_vMat;
};

template<class ELE,class ELE2>
void MinSelf(ELE* seft, const ELE2& other)
{
	*seft = min(*seft,(ELE) other);
}

template<class ELE>
void MaxSelf(ELE* seft, const ELE& other)
{
	*seft = max(*seft, other);
}

class Solution {
public:
	vector<string> maxNumOfSubstrings(string s) {
		vector<int> indexs[26];
		for (int i = 0; i < s.length(); i++)
		{
			indexs[s[i] - 'a'].emplace_back(i);
		}
		vector<vector<int>> mat(26, vector<int>(26,1000'000'000));
		for (int i = 0; i < 26; i++)
		{
			if (indexs[i].empty()) { continue; }			
			for (int j = 0; j < 26; j++)
			{
				auto it1 = std::lower_bound(indexs[j].begin(), indexs[j].end(), indexs[i].front());
				auto it2 = std::upper_bound(indexs[j].begin(), indexs[j].end(), indexs[i].back());
				if (it2 - it1 > 0 )
				{
					mat[i][j] = 1;
				}
			}
		}
		CFloyd floyd(mat);
		vector<pair<int, int>> rl;
		for (int i = 0; i < 26; i++)
		{			
			int left = 1000'000, r = -1;
			for (int j = 0; j < 26; j++)
			{
				if (floyd.m_vMat[i][j] < 1000'000'000)
				{
					MinSelf(&left, indexs[j].front());
					MaxSelf(&r, indexs[j].back());
				}
			}
			if (-1 == r)
			{
				continue;
			}
			rl.emplace_back(r, left);
		}
		sort(rl.begin(), rl.end());
		int end = -1;
		vector<string> vAns;
		for (const auto& [r, left] : rl)
		{
			if (left > end)
			{
				vAns.emplace_back(s.substr(left, r - left + 1));
				end = r;
			}
		}
		return vAns;
	}
	
};

测试用例


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()
{
	string s;
	{
		Solution sln;
		s = "cabcccbaa";
		auto res = sln.maxNumOfSubstrings(s);
		Assert({ "cabcccbaa" }, res);
	}
	{
		Solution sln;
		s = "ababa";
		auto res = sln.maxNumOfSubstrings(s);
		Assert({ "ababa" }, res);
	}
	{
		Solution sln;		
		s = "adefaddaccc";
		auto res = sln.maxNumOfSubstrings(s);
		Assert({ "e","f","ccc" }, res);
	}
	

	{
		Solution sln;
		s = "abbaccd";
		auto res = sln.maxNumOfSubstrings(s);
		Assert({ "bb","cc","d" }, res);
	}
}

2023年5月

class Solution {
public:
vector maxNumOfSubstrings(string s) {
vector<vector> vIndexs(26);
int index = 0;
for (const char&ch : s)
{
vIndexs[ch - ‘a’].emplace_back(index++);
}
vector<std::pair<int, int>> vEndLen;
m_vNeib.resize(26);
for (int i = 0; i < 26; i++)
{
const auto& v = vIndexs[i];
if (v.empty())
{
continue;
}
int begin = v.front();
int end = v.back();
Do(begin, end, vIndexs);
vEndLen.emplace_back(end, end-begin + 1);
}
std::sort(vEndLen.begin(), vEndLen.end());
int iEnd = -1;
vector vRet;
for (int i = 0; i < vEndLen.size(); i++)
{
const int iBegin = vEndLen[i].first - vEndLen[i].second + 1;
if (iBegin > iEnd)
{
iEnd = vEndLen[i].first;
vRet.emplace_back(s.substr(iBegin, vEndLen[i].second));
}
}
return vRet;
}
void Do(int& begin, int& end, const vector<vector>& vIndexs)
{
for (int i = 0; i < 26; i++)
{
const auto& v = vIndexs[i];
const int iNum = std::upper_bound(v.begin(), v.end(), end) - std::lower_bound(v.begin(), v.end(), begin);
if (0 == iNum)
{
continue;
}
if ((v.front() < begin) || (v.back() > end))
{
begin = min(begin, v.front());
end = max(end, v.back());
Do(begin, end, vIndexs);
break;
}
}
}
vector<vector> m_vNeib;
};

2023年9月

class Solution {
public:
vector maxNumOfSubstrings(string s) {
vector<vector> vIndexs(26);
for (int i = 0; i < s.length(); i++)
{
const int index = s[i] - ‘a’;
vIndexs[index].emplace_back(i);
}
for (int i = 0; i < 26; i++)
{
if (vIndexs[i].empty())
{
continue;
}
DoRightLeft(vIndexs[i].front(), vIndexs[i].back(), vIndexs);
}
sort(m_vRightLeft.begin(), m_vRightLeft.end());
int iPreEnd = -1;
vector vRet;
for (const auto& [r, left] : m_vRightLeft)
{
const int len = r - left + 1;
if (left > iPreEnd)
{
vRet.emplace_back(s.substr(left, len));
iPreEnd = r;
}
}
return vRet;
}
void DoRightLeft(int left, int r, const vector<vector>& vIndexs)
{
bool bAdd = false;
for (int i = 0; i < 26; i++)
{
const auto& v = vIndexs[i];
const int iNum = std::upper_bound(v.begin(), v.end(), r) - std::lower_bound(v.begin(), v.end(), left);
if (0 == iNum)
{
continue;
}
if ((v.front() < left) || (v.back() > r))
{
bAdd = true;
left = min(left, v.front());
r = max(r, v.back());
DoRightLeft(left, r, vIndexs);
break;
}
}
if (bAdd)
{
return;
}
m_vRightLeft.emplace_back(r, left);
}
vector<pair<int,int>> m_vRightLeft;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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/488246.html

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

相关文章

LeetCode 面试经典150题 392.判断子序列

题目&#xff1a; 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是"abcde"…

量子计算新“尺度”:用经典计算机评估复杂量子系统!

未来的量子计算机有望在计算机科学、医疗、商业、化学、物理学等多个领域解决难题&#xff0c;从而超越传统计算机。然而&#xff0c;目前的量子计算机仍存在局限&#xff0c;主要是由于它们固有的错误率。为此&#xff0c;研究者正致力于降低这些错误率。 一种研究量子计算机误…

Linux 性能优化

性能优化 性能指标 高并发和响应快对应着性能优化的两个核心指标&#xff1a;吞吐和延时 应用负载角度&#xff1a;直接影响了产品终端的用户体验 系统资源角度&#xff1a;资源使用率、饱和度等 性能问题的本质就是系统资源已经到达瓶颈&#xff0c;但请求的处理还不够快…

Gemma开源AI指南

近几个月来&#xff0c;谷歌推出了 Gemini 模型&#xff0c;在人工智能领域掀起了波澜。 现在&#xff0c;谷歌推出了 Gemma&#xff0c;再次引领创新潮流&#xff0c;这是向开源人工智能世界的一次变革性飞跃。 与前代产品不同&#xff0c;Gemma 是一款轻量级、小型模型&…

Linux 搭建jenkins docker

jekin docker gitee docker 安装 jenkins docker run -d --restartalways \ --name jenkins -uroot -p 10340:8080 \ -p 10341:50000 \ -v /home/docker/jenkins:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /usr/bin/docker:/usr/bin/docker je…

【NLP学习记录】Embedding和EmbeddingBag

Embedding与EmbeddingBag详解 ●&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 ●&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 ●&#x1f680; 文章来源&#xff1a;K同学的学习圈子1、Embedding详解 Embedding是Pytorch中最基本…

VR全景展示:传统制造业如何保持竞争优势?

在结束不久的两会上&#xff0c;数字化经济和创新技术再度成为了热门话题。我国制造产业链完备&#xff0c;但是目前依旧面临着市场需求不足、成本传导压力加大等因素影响&#xff0c;那么传统制造业该如何保持竞争优势呢&#xff1f; 在制造行业中&#xff0c;VR全景展示的应用…

图解Kafka架构学习笔记(二)

kafka的存储机制 https://segmentfault.com/a/1190000021824942 https://www.lin2j.tech/md/middleware/kafka/Kafka%E7%B3%BB%E5%88%97%E4%B8%83%E5%AD%98%E5%82%A8%E6%9C%BA%E5%88%B6.html https://tech.meituan.com/2015/01/13/kafka-fs-design-theory.html https://feiz…

第十二届蓝桥杯物联网试题(省赛)

思路&#xff1a; 这个考了一个RTC的配置&#xff0c;RTC我只配过一次&#xff0c;所以有些生疏&#xff0c;还是不能大意&#xff0c;一些偏僻的考点还是要多练&#xff0c;在获取RTC时间的时候也遇到一些bug,这个后续会用一篇博客将最近遇到的BUG都总结一下 主要的难点还是…

纯前端调用本机原生Office实现Web在线编辑Word/Excel/PPT,支持私有化部署

在日常协同办公过程中&#xff0c;一份文件可能需要多次重复修改才能确定&#xff0c;如果你发送给多个人修改后再汇总&#xff0c;这样既效率低又容易出错&#xff0c;这就用到网页版协同办公软件了&#xff0c;不仅方便文件流转还保证不会出错。 但是目前一些在线协同Office…

好莱坞新风潮:OpenAI携手Sora AI视频生成工具探索电影制作新境界

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

24.两两交换链表中的节点

给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#xff1a;[2,1,4…

Qt|QStringList转QString

免责&#xff1a;百度搜索AI自动生成&#xff0c;如果侵权联系我删除。 AI生成有错误&#xff0c;已验证修改。 文章目录 1.使用join()方法&#xff1a;2.使用QTextStream&#xff1a;3.使用QString的arg()方法&#xff1a;4.使用std::for_each和lambda表达式&#xff1a;5.使…

elasticsearch 6.8.x 索引别名、动态索引扩展、滚动索引

文章目录 引言索引别名&#xff08;alias&#xff09;创建索引别名查询索引别名删除索引别名重命名索引别名 动态索引&#xff08;index template&#xff0c;动态匹配生成索引&#xff09;新建索引模板新建索引并插入数据索引sys-log-202402索引sys-log-202403索引sys-log-202…

android studio忽略文件

右键文件&#xff0c;然后忽略&#xff0c;就不会出现在commit里面了 然后提交忽略文件即可

【算法专题--双指针算法】leecode-15.三数之和(medium)、leecode-18. 四数之和(medium)

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1. 三数之和2. 解法&…

龙蜥 Anolis OS 7.9 一键安装 Oracle 11GR2(231017)单机版

前言 Oracle 一键安装脚本&#xff0c;演示 龙蜥 Anolis OS 7.9 一键安装 Oracle 11GR2&#xff08;231017&#xff09;单机版过程&#xff08;全程无需人工干预&#xff09;&#xff1a;&#xff08;脚本包括 ORALCE PSU/OJVM 等补丁自动安装&#xff09; ⭐️ 脚本下载地址…

【编译tingsboard】出现gradle-maven-plugin:1.0.11:invoke (default)

出现的错误&#xff1a; [ERROR] Failed to execute goal org.thingsboard:gradle-maven-plugin:1.0.11:invoke (default) on project http: Execution default of goal org.thingsboard:gradle-maven-plugin:1.0.11:invoke failed: Plugin org.thingsboard:gradle-maven-plugi…

uni-app框架(项目创建)

1.学习说明 dcloud官方除uni-app外&#xff0c;还有新生的uni-app x&#xff08;即下一代uni-app&#xff09;&#xff0c;如果是初学者或者刚入门同学&#xff0c;建议还是使用uni-app进行开发。 无论是vue还是uni&#xff0c;作为前端开发的一个框架学习方法是一致的&#…

了解一波经典的 I/O 模型

最近读了波网络 I/O 相关的文章&#xff0c;做下总结、摘录。&#xff08;未完&#xff09; 经典 I/O 模型 {% checkbox red checked, 阻塞式 I/O&#xff08;blocking I/O&#xff09; %}{% checkbox red checked, 非阻塞式 I/O&#xff08;non-blocking I/O&#xff09; %}…