【离散差分】LeetCode2953:统计完全子字符串

作者推荐

[二分查找]LeetCode2040:两个有序数组的第 K 小乘积

本题其它解法

【滑动窗口】LeetCode2953:统计完全子字符串

涉及知识点

分块循环 离散差分

题目

给你一个字符串 word 和一个整数 k 。
如果 word 的一个子字符串 s 满足以下条件,我们称它是 完全字符串:
s 中每个字符 恰好 出现 k 次。
相邻字符在字母表中的顺序 至多 相差 2 。也就是说,s 中两个相邻字符 c1 和 c2 ,它们在字母表中的位置相差 至多 为 2 。
请你返回 word 中 完全 子字符串的数目。
子字符串 指的是一个字符串中一段连续 非空 的字符序列。
示例 1:
输入:word = “igigee”, k = 2
输出:3
解释:完全子字符串需要满足每个字符恰好出现 2 次,且相邻字符相差至多为 2 :igigee, igigee, igigee 。
示例 2:
输入:word = “aaabbbccc”, k = 3
输出:6
解释:完全子字符串需要满足每个字符恰好出现 3 次,且相邻字符相差至多为 2 :aaabbbccc, aaabbbccc, aaabbbccc, aaabbbccc, aaabbbccc, aaabbbccc 。
参数范围
1 <= word.length <= 105
word 只包含小写英文字母。
1 <= k <= word.length

解法一:离散化差分

分块循环处理条件二

我们可以将word拆分若干字串,相邻字符相差超过2时拆分。

变量解析

vIndex记录26个字母的索引
mDiff差分有序映射,记录那些索引是合法的完全字串的开始。合法范围必须是26个字母合法,每个字母的合法范围是:每有此字母或有k个此字母。

时间复杂度

O(nm1logm2),n是字符串的长度,m1是字母数,m2是mDiff的长度,不超过26*4。超时

代码

核心代码

class Solution {
public:
int countCompleteSubstrings(string word, int k) {
m_iK = k;
int pre = 0;
int iRet = 0;
for (int i = 0; i < word.length(); i++)
{
if (i && (abs(word[i] - word[i - 1]) > 2))
{
iRet += Do(word.substr(pre, i - pre));
pre = i ;
}
}
iRet += Do(word.substr(pre, word.length()));
return iRet;
}
int Do(const string& s)
{
int iRet = 0;
vector<vector> vIndex(26, vector(1, -1));
for (int i = 0 ; i < s.length();i++ )
{
const auto& ch = s[i];
vIndex[ch - ‘a’].emplace_back(i);
iRet += GetNum(vIndex,i);
std::cout << “i " << i << " iRet:” << iRet << std::endl;
}
return iRet;
}
int GetNum(const vector<vector>& vIndex,int cur)
{
std::map<int, int> mDiff;
for (int j = 0; j < 26; j++)
{
const auto& v = vIndex[j];
//不选择字母’a’+j
mDiff[v.back()+1]++;
mDiff[cur+1]–;
//选择k个字母
if (v.size() > m_iK )
{
//左开右闭空间
const int iMin = v[v.size() - m_iK-1];
const int iMax = v[v.size() - m_iK ];
mDiff[iMin+1]++;
mDiff[iMax+1]–;
}
}
int iCnt = 0;
int iRet = 0;
for ( auto it = mDiff.begin(); it != mDiff.end(); ++it )
{
iCnt += it->second;
if (26 == iCnt)
{
iRet += std::next(it)->first - it->first;
}
}
return iRet;
}
int m_iK;
};

测试用例

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

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

int main()
{
string s;
int k, res;
{
Solution slu;
s = “gvgvvgv”;
k = 2;
auto res = slu.countCompleteSubstrings(s, k);
Assert(1, res);
}
{
Solution slu;
s = “igigee”;
k = 2;
auto res = slu.countCompleteSubstrings(s, k);
Assert(3, res);
}
{
Solution slu;
s = “aaabbbccc”;
k = 3;
auto res = slu.countCompleteSubstrings(s, k);
Assert(6, res);
}

//CConsole::Out(res);

}

优化

一,mDiff 不用每次都重写处理,只处理当前字母的变化。
二,vIndex 第一维用原生数组。

优化后代码

class Solution {
public:int countCompleteSubstrings(string word, int k) {m_iK = k;int pre = 0;int iRet = 0;for (int i = 0; i < word.length(); i++){if (i && (abs(word[i] - word[i - 1]) > 2)){iRet += Do(word.substr(pre, i - pre));pre = i;}}iRet += Do(word.substr(pre, word.length()));return iRet;}int Do(const string& s){for (int i = 0; i < 26; i++){if( vIndex[i].empty()){vIndex[i].emplace_back(-1);}else if(vIndex[i].size() > 1){vIndex[i].erase(vIndex[i].begin() + 1, vIndex[i].end());}}int iRet = 0;std::map<int, int> mDiff;		mDiff[0] = 26;for (int i = 0; i < s.length(); i++){vector<int>& v = vIndex[s[i] - 'a'];Change(v, mDiff, -1);v.emplace_back(i);Change(v, mDiff, 1);iRet += GetNum(mDiff,i);}return iRet;}void Add(std::map<int, int>& mDiff, const int index, int iChange = 1){mDiff[index] += iChange;if (0 == mDiff[index]){mDiff.erase(index);}}void Change(const vector<int>& v, std::map<int, int>& mDiff, int iAdd ){Add(mDiff,v.back()+1, iAdd);if (v.size() > m_iK){const int iMin = v[v.size() - m_iK - 1];const int iMax = v[v.size() - m_iK];Add(mDiff, iMin + 1, iAdd);Add(mDiff, iMax + 1, -iAdd);}}int GetNum(std::map<int, int>& mDiff,int cur){int iCnt = 0;int iRet = 0;for (auto it = mDiff.begin(); it != mDiff.end(); ++it){iCnt += it->second;if (26 == iCnt){const auto itNext = std::next(it);iRet +=  (( mDiff.end() == itNext) ? cur+1 :  std::next(it)->first) - it->first;}}return iRet;}vector<int> vIndex[26];int m_iK;
};

扩展阅读

视频课程

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

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

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

相关文章

云原生之深入解析如何限制Kubernetes集群中文件描述符与线程数量

一、背景 linux 中为了防止进程恶意使用资源&#xff0c;系统使用 ulimit 来限制进程的资源使用情况&#xff08;包括文件描述符&#xff0c;线程数&#xff0c;内存大小等&#xff09;。同样地在容器化场景中&#xff0c;需要限制其系统资源的使用量。ulimit: docker 默认支持…

08、分析测试执行时间及获取pytest帮助

官方用例 # content of test_slow_func.py import pytest from time import sleeppytest.mark.parametrize(delay,(1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.0,0.1,0.2,0,3)) def test_slow_func(delay):print("test_slow_func {}".format(delay))sleep(delay)assert…

同旺科技 USB TO SPI / I2C --- 调试W5500_TCP Client测试

所需设备&#xff1a; 内附链接 1、USB转SPI_I2C适配器(专业版); 首先&#xff0c;连接W5500模块与同旺科技USB TO SPI / I2C适配器&#xff0c;如下图&#xff1a; 网关IP地址寄存器(192.168.1.1)子网掩码寄存器(255.255.255.0)源MAC地址寄存器源IP地址寄存器(192.168.1.8)…

QT4和 QT5 槽函数连接的区别

正常连接方式 //QT4官方用列QLabel *label new QLabel;QScrollBar *scrollBar new QScrollBar;QObject::connect(scrollBar, SIGNAL(valueChanged(int)),label, SLOT(setNum(int)));//QT5官方用列QLabel *label new QLabel;QLineEdit *lineEdit new QLineEdit;QObject::c…

STK Components 二次开发-飞行器

1.创建飞机 参数帮助文档 var poitList GetTracksData(); var waypointPropagator new WaypointPropagator(m_earth, poitList); var locationPoint waypointPropagator.CreatePoint();m_aircraft new Platform {Name "MH730",LocationPoint locationPoint,Or…

vue3 中使用 sse 最佳实践,封装工具

工具 // 接受参数 export interface SSEChatParams {url: string,// sse 连接onmessage: (event: MessageEvent) > void,// 处理消息的函数onopen: () > void,// 建立连接触发的事件finallyHandler: () > void,// 相当于 try_finally 中的 finally 部分&#xff0c;不…

机器学习(2)回归

0.前提 上一期&#xff0c;我们简单的介绍了一些有关机器学习的内容。学习机器学习的最终目的是为了服务我未来的毕设选择之一——智能小车&#xff0c;所以其实大家完全可以根据自己的需求来学习这门课&#xff0c;我做完另一辆小车后打算花点时间去进行一次徒步行&#xff0…

20:kotlin 类和对象 --泛型(Generics)

类可以有类型参数 class Box<T>(t: T) {var value t }要创建类实例&#xff0c;需提供类型参数 val box: Box<Int> Box<Int>(1)如果类型可以被推断出来&#xff0c;可以省略 val box Box(1)通配符 在JAVA泛型中有通配符?、? extends E、? super E&…

25. K 个一组翻转链表

给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值…

自媒体原创改写工具,自媒体首发改写软件

自媒体平台已成为许多创作者表达观点、分享知识和积累影响力的关键渠道。创作是需要技巧和经验的。本文将分享一些自媒体文章改写技巧&#xff0c;并推荐一系列优秀的自媒体文章改写工具&#xff0c;帮助您提升创作效率&#xff0c;创作出更优秀的文章。 自媒体文章改写技巧 …

Backend - Django makemigrations

目录 一、迁移命令 &#xff08;一&#xff09;前提 &#xff08;二&#xff09;生成迁移文件 &#xff08;三&#xff09;执行迁移 二、迁移问题 1. Error&#xff1a;No changes detected 2. Error&#xff1a;You are trying to add a non-nullable field XXX to XXX…

[读论文]BK-SDM: A Lightweight, Fast, and Cheap Version of Stable Diffusion

github: GitHub - Nota-NetsPresso/BK-SDM: A Compressed Stable Diffusion for Efficient Text-to-Image Generation [ICCV23 Demo] [ICML23 Workshop] ICML 2023 Workshop on ES-FoMo 简化方式 蒸馏方式&#xff08;训练Task蒸馏outKD-FeatKD&#xff09; 训练数据集 评测指标…

在intelliJ spring boot gradle插件3.2.0中未找到匹配的变量

我正在尝试使用spring启动Gradle插件的版本3.2.0。这是我的build.gradle文件&#xff1a; plugins {id javaid org.springframework.boot version 3.2.0id io.spring.dependency-management version 1.1.4 }group com.yaxin version 0.0.1-SNAPSHOTjava {sourceCompatibilit…

GPIO的使用--时钟使能含义--代码封装

目录 一、时钟使能的含义 1.为什么要时钟使能&#xff1f; 2.什么是时钟使能&#xff1f; 3.GPIO的使能信号&#xff1f; 二、代码封装 1.封装前完整代码 2.封装结构 封装后代码 led.c led.h key.c key.h main.c 一、时钟使能的含义 1.为什么要时钟使能&#xff1f…

Python开发运维:Python 3.8 常用标准库

目录 一、理论 1.Python3.8 标准库 2.常用标准库 二、问题 1.Python 正则表达式如何实现 一、理论 1.Python3.8 标准库 &#xff08;1&#xff09;官网 Python 标准库 — Python 3.8.17 文档 &#xff08;2&#xff09;其他版本下拉列表查询 2.常用标准库 &#xff0…

MySQL笔记-第01章_数据库概述

视频链接&#xff1a;【MySQL数据库入门到大牛&#xff0c;mysql安装到优化&#xff0c;百科全书级&#xff0c;全网天花板】 文章目录 第01章_数据库概述1. 为什么要使用数据库2. 数据库与数据库管理系统2.1 数据库的相关概念2.2 数据库与数据库管理系统的关系2.3 常见的数据库…

Linux--网络编程-ftp(TCP)网络通信-文件交互

项目要求&#xff1a;实现以下内容 远程控制&#xff1a; 1、查看服务器当前路径文件 ls 3、进入、退出服务器文件夹 cd 4、上传文件到服务器 put xxx 本地控制&#xff1a; 1、查看本地&#xff08;客户端&#xff09;文件 lls 2、进入客户端文件夹 lcd 3、获取服务器的文件…

音频录制软件哪个好?帮助你找到最合适的一款

音频录制软件是日常工作、学习和创作中不可或缺的一部分。选择一个适合自己需求的录音软件对于确保音频质量和提高工作效率至关重要。可是您知道音频录制软件哪个好吗&#xff1f;本文将深入探讨两种常见的音频录制软件&#xff0c;通过详细的步骤指南&#xff0c;帮助您了解它…

编写Java应用程序,输出满足1+2+3+……+n<8888的最大正整数n。

源代码&#xff1a; public class Main { public static void main(String[] args) { int i 1; int sum 0; for(i 1;;i){ sum i; if (sum >8888) break; } System.out.println(i-1); } } 实验运行截图&#xff1a;

【滑动窗口】LeetCode2953:统计完全子字符串

作者推荐 [二分查找]LeetCode2040:两个有序数组的第 K 小乘积 本题其它解法 【离散差分】LeetCode2953:统计完全子字符串 题目 给你一个字符串 word 和一个整数 k 。 如果 word 的一个子字符串 s 满足以下条件&#xff0c;我们称它是 完全字符串&#xff1a; s 中每个字符…