【map】【滑动窗口】【字典树】C++算法:最长合法子字符串的长度

作者推荐

动态规划 多源路径 字典树 LeetCode2977:转换字符串的最小成本

本题涉及知识点

滑动窗口字典树 map 离线查询

map

map可以分成有序(单调)map和无序(哈希)map。还可分成单键map和多键map(允许重复的键)。本文用:单键无序map。

LeetCode2781:最长合法子字符串的长度

给你一个字符串 word 和一个字符串数组 forbidden 。
如果一个字符串不包含 forbidden 中的任何字符串,我们称这个字符串是 合法 的。
请你返回字符串 word 的一个 最长合法子字符串 的长度。
子字符串 指的是一个字符串中一段连续的字符,它可以为空。
示例 1:
输入:word = “cbaaaabc”, forbidden = [“aaa”,“cb”]
输出:4
解释:总共有 11 个合法子字符串:“c”, “b”, “a”, “ba”, “aa”, “bc”, “baa”, “aab”, “ab”, “abc” 和 “aabc”。最长合法子字符串的长度为 4 。
其他子字符串都要么包含 “aaa” ,要么包含 “cb” 。
示例 2:
输入:word = “leetcode”, forbidden = [“de”,“le”,“e”]
输出:4
解释:总共有 11 个合法子字符串:“l” ,“t” ,“c” ,“o” ,“d” ,“tc” ,“co” ,“od” ,“tco” ,“cod” 和 “tcod” 。最长合法子字符串的长度为 4 。
所有其他子字符串都至少包含 “de” ,“le” 和 “e” 之一。
参数范围
1 <= word.length <= 105
word 只包含小写英文字母。
1 <= forbidden.length <= 105
1 <= forbidden[i].length <= 10
forbidden[i] 只包含小写英文字母。

滑动窗口+离线查询+map

时间复杂度😮(nmm+nlogn+n)。m = max(forbidden[i].length)为10
第一步:如果s[left,right]等于 forbidden中任何一个字符串,记录在vLeftRight中。本问题等效与:不能包括任意[left,right]的最长子串。
第二步:排序vLeftRight。
第三步:从大到小枚举合法子串的左边界i,计算最大右边界j。
如果s[left,right]等于某个禁止串

left<i无论j为何值,都不会包括对应的禁止串,因为s[left]不在对应的子串中
left>=ij的取值范围为[i,right),不能取值right ,否则s[left,right] 就在word[i,j]中。如果多个无法合法的right,取最小值。如果没有合法的right,取m_c。

离线查询

由于vLeftRight 已经按left排序,每次处理i之前,先用left >= i的right更新iMin。

代码

核心代码

class Solution {
public:int longestValidSubstring(string word, vector<string>& forbidden) {m_c = word.length();std::unordered_set<string> setHas(forbidden.begin(), forbidden.end());vector<pair<int, int>> vLeftRight;for (int len = 1; len <= 10; len++){for (int left = 0; left + len <= m_c; left++){if (setHas.count(word.substr(left, len))){vLeftRight.emplace_back(left, left + len - 1);}}}sort(vLeftRight.begin(), vLeftRight.end());int iRet = 0;int iMin = m_c;for (int i = m_c - 1; i >= 0; i--){while (vLeftRight.size() && (vLeftRight.back().first >= i)){iMin = min(iMin, vLeftRight.back().second);vLeftRight.pop_back();}iRet = max(iRet, iMin - i);}return iRet;}int m_c;
};

字典树

可以利用字典树,将第一步的时间复杂度降到O(nm)。

template<class TData, TData defData,int iTypeNum = 26, TData cBegin = 'a'>
class CTrie
{
public:CTrie() {m_iID = s_ID++;}int GetLeadCount(){return m_iLeafCount;}template<class IT>int Add(IT begin, IT end){int iLeve = 0;CTrie* pNode = this;for (; begin != end; ++begin){pNode = pNode->AddChar(*begin);			pNode->m_iLeve = iLeve++;}if (-1 == pNode->m_iLeafID){pNode->m_iLeafID = ++m_iLeafCount;}return pNode->m_iLeafID;}template<class IT>CTrie* Search(IT begin, IT end){if (begin == end){return this;}if ('.' == *begin){for (auto& ptr : m_vPChilds){if (!ptr){continue;}auto pSearch = ptr->Search(begin + 1, end);if (pSearch){return pSearch;}}return nullptr;}auto ptr = GetChild(*begin);if (nullptr == ptr){return nullptr;}return ptr->Search(begin + 1, end);}CTrie* AddChar(TData ele){if ((ele < cBegin) || (ele >= cBegin + iTypeNum)){return nullptr;}const int index = ele - cBegin;auto ptr = m_vPChilds[index];if (!ptr){m_vPChilds[index] = new CTrie();}return m_vPChilds[index];}CTrie* GetChild(TData ele)const{if ((ele < cBegin) || (ele >= cBegin + iTypeNum)){return nullptr;}return m_vPChilds[ele - cBegin];}
protected:int m_iID;
public:int m_iLeafID=-1;
protected:int m_iLeve=-1;inline static int s_ID = 0;int m_iLeafCount = 0;CTrie* m_vPChilds[iTypeNum] = { nullptr };
};class Solution {
public:int longestValidSubstring(string word, vector<string>& forbidden) {m_c = word.length();CTrie<char,'a'> trie;for (const auto& s : forbidden){trie.Add(s.begin(), s.end());}vector<pair<int, int>> vLeftRight;for (int left = 0; left < m_c ; left++){CTrie<char,'a'>* p = &trie;for (int len = 1; left + len <= m_c; len++){p = p->GetChild(word[left + len - 1]);if (nullptr == p){break;}if (p->m_iLeafID > 0){vLeftRight.emplace_back(left, left + len - 1);}}}sort(vLeftRight.begin(), vLeftRight.end());int iRet = 0;int iMin = m_c;for (int i = m_c - 1; i >= 0; i--){while (vLeftRight.size() && (vLeftRight.back().first >= i)){iMin = min(iMin, vLeftRight.back().second);vLeftRight.pop_back();}iRet = max(iRet, iMin - i);}return iRet;}int m_c;
};

2023年7月版

class Solution {
public:
int longestValidSubstring(string word, vector& forbidden) {
m_pHash = std::make_shared< CHashStr<>>(word,26);
std::unordered_set setCode[11];
for (const string& s : forbidden)
{
const int len = s.length();
CHashStr< > hash(s,26);
auto llCode = hash.GetHashExincludeRight(len);
setCode[len].emplace(llCode);
}
std::map<int, int> mEndLen;
for (int i = 0; i < word.size(); i++)
{
for (int len = 1; len <= 10 ; len++)
{
const int end = i + len;
if (end > word.size())
{
continue;
}
int llCode = m_pHash->GetHashExincludeRight(i, end);
if (setCode[len].end() != setCode[len].find(llCode))
{
//目标串不能包括[1,i+len)
mEndLen[i+len] = len;
break;
}
}
}
int begin = 0;
int iMaxLen = 0;
for (const auto& it : mEndLen)
{
const int iCurLen = it.first - begin-1;
iMaxLen = max(iMaxLen, iCurLen);
begin = max(begin,it.first - it.second+ 1);
}
iMaxLen = max(iMaxLen, (int)word.size() - begin);
return iMaxLen;
}
std::shared_ptr< CHashStr<> > m_pHash;
};

扩展阅读

视频课程

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

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

相关文章

防弹防线:彻底击败Redis缓存穿透问题【redis问题 一】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 防弹防线&#xff1a;彻底击败Redis缓存穿透问题 前言1. 缓存穿透定义和成因定义&#xff1a;缓存穿透的隐秘入侵成因分析&#xff1a;揭秘缓存穿透的幕后黑手故事描述 2. 缓存穿透的影响对数据库的影…

最优轨迹生成(三)—— 无约束BIVP轨迹优化

本系列文章是学习深蓝学院-移动机器人运动规划课程第五章最优轨迹生成 过程中所记录的笔记&#xff0c;本系列文章共包含四篇文章&#xff0c;依次介绍了微分平坦特性、无约束BVP轨迹优化、无约束BIVP轨迹优、 带约束轨迹优化等内容 本系列文章链接如下&#xff1a; 最优轨迹生…

设计模式详解:代理模式

1. 什么是代理模式&#xff1f; 代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许通过代理对象控制对另一个对象的访问。代理模式在客户端和目标对象之间引入了一个代理对象&#xff0c;客户端通过代理对象间接地访问目标对象&#xff0c…

以太坊代币标准解读及相关Dapp的搭建

文章目录 什么是以太坊代币标准1、什么是以太坊2、以太坊代币标准 同质化代币 Dapp 搭建1、MetaMask 的安装2、Ganache 的安装3、实现 ERC-20 代币协议4、前端页面的编写5、部署流程及操作演示 什么是以太坊代币标准 1、什么是以太坊 以太坊&#xff08;Ethereum&#xff09;是…

idea构建maven项目报错的解决

使用idea创建了一个新的spring项目&#xff0c;maven配置完毕后&#xff0c;报错&#xff0c;引用的依赖不存在。 控制台报错信息如下&#xff1a; 通过查询资料&#xff0c;发现是阿里云的maven仓库中没有这个版本的jar包&#xff0c;导入无法引用到对应的依赖。 解决方法就是…

01 HAL库点亮LED灯

引言&#xff1a;本专题采取的开发平台是stm32cubeIDE&#xff0c; 文章后面会后提供 一 、 LED简介 LED&#xff08;Light Emitting Diode&#xff09;是一种半导体发光器件&#xff0c;能够将电能直接转化为光能的电子元件。它具有体积小、功耗低、寿命长等特点&#xff0c;广…

接入Cloudflare后Nginx和Django获取用户真实IP的办法

可以用Nginx的real_ip的相关命令来实现这个需求。 01-real_ip命令集详解 real_ip命令的使用分为两个步骤: 01-1-设置从哪些代理IP获取真实IP 第1个步骤&#xff1a;通过set_real_ip_from命令设置从哪些代理IP请求获取真实的IP,比如下面的命令&#xff1a; set_real_ip_from…

Navicat for MySQL 创建函数——报错1418

解决方法 1查看是否开启了创建函数的功能 输入下面语句查看是否开启了创建函数的功能 show variables like %func%; 下面为创建函数功能为开启的查询结果 如果不是上面的结果可以用下面的语句修改为开启 set GLOBAL log_bin_trust_function_creatorstrue; //或 set GLOBAL …

【一分钟】ThinkPHP v6.0 (poc-yaml-thinkphp-v6-file-write)环境复现及poc解析

写在前面 一分钟表示是非常短的文章&#xff0c;只会做简单的描述。旨在用较短的时间获取有用的信息 环境下载 官方环境下载器&#xff1a;https://getcomposer.org/Composer-Setup.exe 下载文档时可以设置代理&#xff0c;不然下载不上&#xff0c;你懂的 下载成功 cmd cd…

Redis经典五大类型源码及底层实现(二)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…

数据结构:第7章:查找(复习)

顺序查找&#xff1a; ASL 折半查找&#xff1a; 这里 j 表示 二叉查找树的第 j 层 二叉排序树&#xff1a; 二叉排序树&#xff08;Binary Search Tree&#xff0c;BST&#xff09;是一种特殊的二叉树&#xff0c;定义&#xff1a; 对于二叉排序树的每个节点&#xff0c;…

全球电商平台API数据稳定接入

API是什么&#xff1f; API就是接口&#xff0c;就是通道&#xff0c;负责一个程序和其他软件的沟通&#xff0c;本质是预先定义的函数。”比如&#xff1a;电脑需要调用手机里面的信息&#xff0c;这时候你会拿一根数据线将电脑手机连接起来&#xff0c;电脑和手机上连接数据…

Linux学习笔记(一)

如果有自己的物理服务器请先查看[这篇文章](https://blog.csdn.net/yasinawolaopo/article/details/132391128)文章目录 网卡配置Linux基础指令ls:列出目录内容cd(mkdir.rmkdir): 切换文件夹(创建,删除操作)cp:复制文件或目录mv:文件/文件夹移动cat:查看文件vi:文件查看编辑man…

二进制文件分割器

二进制文件分割器 时间: 2023.12.29 作者: FlameCyclone 自己写的一个能方便分割文件的小工具 使用说明 输出文件名 输出文件名规则前缀文件名开始固定名称序号(10/16进制显示, 宽度以输出最大序号为准)分割范围(16进制显示, 宽度以输出最大范围为准)CRC32校验码8字符组成…

touchHLE实战之游戏

前面推荐了touchHLE&#xff0c;号称可以玩旧的IOS游戏&#xff0c;但是国外还是管理的很严格的&#xff0c;一直没有找到合适的游戏文件测试。最近&#xff0c;发现官网上公布了开发者赠送的一款游戏&#xff0c;试了下完美运行。 看到国外贴吧reddit上有人推荐可用的ipa资源&…

蓝桥杯C/C++程序设计——成绩统计

题目描述 小蓝给学生们组织了一场考试&#xff0c;卷面总分为 100 分&#xff0c;每个学生的得分都是一个 0 到 100 的整数。 如果得分至少是 60 分&#xff0c;则称为及格。如果得分至少为 85 分&#xff0c;则称为优秀。 请计算及格率和优秀率&#xff0c;用百分数表示&am…

不同语言告别2023,迎接2024

一、序言 1.一名合格的程序员&#xff0c;始于Hello World&#xff0c;终于Hello World&#xff0c;用不同语言表达2023最后一天。 2.在这一年里&#xff0c;博主新接触了VUE、Python、人工智能、JAVA的框架SprinBoot、微服务等&#xff0c;然后一路来感谢大家的支持&#xf…

ClickHouse基础知识(一):ClickHouse 入门

1. ClickHouse 入门 ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的列式存储数据库&#xff08;DBMS&#xff09;&#xff0c;使用 C 语言编写&#xff0c;主要用于在线分析处理查询&#xff08;OLAP&#xff09;&#xff0c;能够使用 SQL 查询实时生成分析数据报告。 2. Cl…

python使用selenium控制浏览器进行爬虫

这里以谷歌浏览器为例&#xff0c;需要安装一下chromedriver&#xff0c;其他浏览器也有相对应的driver&#xff0c;chromedriver下载地址&#xff1a;https://googlechromelabs.github.io/chrome-for-testing/ 然后是打开python环境安装一下依赖pip install selenium&#xf…

【低代码平台】10个开源免费Airtable 的替代方案

Airtable是一个易于使用的简单低代码平台&#xff0c;有助于团队协作管理复杂的数据表&#xff0c;并创建定制的工作流程。把它想象成一个类固醇上的云电子表格。 Airtable还简化了数据输入过程&#xff0c;连接和集成第三方服务和应用程序&#xff0c;并提供了许多数据导入/导…