【解析几何】 【多源路径】 【贪心】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++**实现。

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

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

相关文章

Wireshark使用实训---分析IP包

1.Wireshark简介和作用 Wireshark是一个开源的网络分析工具&#xff0c;用于捕捉和分析网络数据包。它可以帮助网络管理员和安全专家监控和解决网络问题&#xff0c;同时也可以用于学习和教学网络通信原理。 Wireshark可以在网络中捕获和分析传输的数据包&#xff0c;包括协议…

【Java初阶(五)】类和对象

❣博主主页: 33的博客❣ ▶文章专栏分类: Java从入门到精通◀ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; 目录 1. 前言2.面向对象的认识3.类的认识4. 类的实例化4.1什么是实例化4.2类和对象的说明 5.this引用6.对象初始化6.1 构造方法 7.static关键字8.代码块8.1 …

PTAxt的考研路

xt是我院19级专业第一&#xff0c;但他认为保研并不能展示他全部的实力&#xff0c;所以他在22年初试一结束就加入了23考研的队伍中&#xff0c;并且他为了填补我院近些年来无北大研究生的空白&#xff0c;毅然决然决定扛起19级的大旗&#xff0c;在学校百年华诞之际献上他最诚…

光明源@智慧公厕赋能“厕所革命”主要体现在哪些方面?

当我们提及厕所&#xff0c;不再仅是简单的卫生设施&#xff0c;而是一种对生活品质的关怀与呵护。智慧公厕&#xff0c;作为厕所革命的引领者&#xff0c;以其独特的拟人魅力&#xff0c;彰显着人性化关怀的新风尚。今日&#xff0c;让我们一同探索&#xff0c;智慧公厕是如何…

数据库备份工具(实现数据定时覆盖)

数据库备份工具&#xff08;实现数据定时覆盖&#xff09; 永远热爱&#xff0c;永远执着&#xff01; 工具介绍 自动化测试数据库更新调度程序 这段 Python 脚本自动化了每天定时从生产数据库更新测试数据库的过程。它利用了 schedule 库来安排并执行每天指定时间的更新任务…

在for循环加判断条件当条件都满足时,同时显现的解决方法

一、代码示例 function fu(s) {str ;ste ;console.log(s);let Things s;for (let i 0; i < Things.length; i) {if (Things[i].pid kk) {console.log(Things[i].pid);ste <div class"commodity_nei"><div class"zxc_pic"><div cl…

[CISCN2019 总决赛 Day2 Web1]Easyweb ----不会编程的崽

CISCN的题质量还是很高的。 又是这熟悉的登陆界面。爆破&#xff1f;sql&#xff1f;还是xxe等。先看源码 估摸着也是sql注入。但似乎不是常规注入。同时扫描后台的结果应该也出来了&#xff0c;发现robots.txt 有点懵&#xff0c;后边看了大佬的wp才知道&#xff0c;提示的是*…

openssl 升级1.1.1.1k 到 3.0.13

下载 https://www.openssl.org/source/ tar -zxvf openssl-3.0.13.tar.gzcd openssl-3.0.13/./config enable-fips --prefix/usr/local --openssldir/usr/local/opensslmake && make install 将原有openssl备份 mv /usr/bin/openssl /usr/bin/openssl.bak mv /usr/i…

LeetCode Python - 73. 矩阵置零

目录 题目描述解法方法一&#xff1a;数组标记方法二&#xff1a;原地标记 运行结果方法一方法二 题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;…

Redis到底是多线程还是单线程?

Redis6.0之前&#xff1a;是单线程模式。 Redis6.0之后&#xff1a;Redis的IO线程是多线程&#xff0c;worker线程是单线程。 Redis6.0之前&#xff1a;单线程 Redis6.0之后&#xff1a;Redis的IO线程是多线程&#xff0c;worker线程是单线程。

适用于 Android 的 10 个优秀的数据恢复工具

在当今快节奏的数字时代&#xff0c;丢失 Android 设备中的重要数据可能是一场噩梦。无论是难忘的照片、重要的联系人还是重要的工作文档&#xff0c;您都需要一个可靠的恢复工具来恢复您的数据。值得庆幸的是&#xff0c;有许多高效的 Android 数据恢复工具可以帮助您恢复丢失…

【python】flask各种版本的项目,终端命令运行方式的实现

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

XUbuntu22.04之跨平台日历工具(二百二十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

WSL2 设置桥接模式

文章目录 一、前言二、准备阶段三、环境配置3.1 Type-V管理器环境配置3.2 新增.wslconfig 文件 四、遇到的问题以及解决方案 一、前言 ​ 使用 wsl 的过程中&#xff0c;会出现 WSL 的IP地址 找不到&#xff0c;或者无法和计算机通讯&#xff0c;搞 嵌入式 的话&#xff0c;还…

网络原理(7)——以太网数据帧和DNS协议(数据链路层和应用层)

目录 一、以太网数据帧&#xff08;数据链路层&#xff09; 二、DNS协议(域名解析系统&#xff0c;应用层协议) 一、以太网数据帧&#xff08;数据链路层&#xff09; 以太网横跨了数据链路层和物理层&#xff0c;这里只做简单介绍&#xff0c;因为普通程序员用不到这一块&am…

浅谈linux下的进程地址空间(虚拟地址/线性地址)

目录 什么是地址空间 - 虚拟地址空间 地址空间是如何设计的 为什么要有地址空间 什么是地址空间&#xff1f; 示例&#xff1a; 运行之后发现&#xff1a;同一个变量&#xff0c;同一个地址&#xff0c;在运行一段时间后&#xff0c;竟然会在同一时间出现两个不同的值&…

阿里云短信平台收费价格表,短信服务优惠0.032元一条

2024年阿里云短信服务优惠价格表&#xff0c;阿里云短信多少钱一条&#xff1f;低至0.01元一条&#xff0c;200条短信仅需2元&#xff0c;最高可领2000条短信免费赠送&#xff0c;短信套餐包2000条、5000条、5万条等均有活动&#xff0c;阿里云百科aliyunbaike.com整理2024年最…

数字乡村战略实施:科技引领农村经济社会全面发展

随着信息技术的快速发展&#xff0c;数字化已经成为推动经济社会发展的重要力量。在乡村振兴战略的大背景下&#xff0c;数字乡村战略的实施成为了引领农村经济社会全面发展的关键。本文将从数字乡村战略的内涵、实施现状、面临挑战及未来展望等方面&#xff0c;探讨科技如何引…

MySQL数据库备份策略与实践详解

目录 引言 一、MySQL数据库备份的重要性 &#xff08;一&#xff09;数据丢失的原因 &#xff08;二&#xff09;数据丢失的后果 二、MySQL备份类型 &#xff08;一&#xff09;根据数据库状态 &#xff08;二&#xff09;根据数据的完整性 &#xff08;三&#xff09;…

线程的状态:操作系统层面和JVM层面

在操作系统层面&#xff0c;线程有五种状态 初始状态&#xff1a;线程被创建&#xff0c;操作系统为其分配资源。 可运行状态(就绪状态)&#xff1a;线程被创建完成&#xff0c;进入就绪队列&#xff0c;参与CPU执行权的争夺。或因为一些原因&#xff0c;从阻塞状态唤醒的线程…