LeetCode.30 串联所有单词的子串

问题描述

给定一个字符串 s 和一个字符串数组 words words 中所有字符串 长度相同

 s 中的 串联子串 是指一个包含  words 中所有字符串以任意顺序排列连接起来的子串。

  • 例如,如果 words = ["ab","cd","ef"], 那么 "abcdef", "abefcd""cdabef", "cdefab""efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。

返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。

解题思路

1. 初步理解

首先需要明确,只有当 s 中的某个子串正好由 words 中所有单词组成,并且每个单词出现一次,才符合条件。这提示我们可以使用组合和检查的策略来找到这些子串。

2. 设计策略

基于以上理解,可以采用以下策略:

  • 长度计算: 计算 words 中所有字符串连接后的总长度,这将是我们在 s 中搜索的子串的长度。
  • 字典统计: 使用一个哈希表(字典)来统计 words 数组中每个单词的出现频率。
  • 滑动窗口: 在字符串 s 上滑动一个固定大小的窗口,并在窗口内部维护一个字典来记录当前窗口中各单词的出现频率。
  • 窗口调整: 根据窗口内单词的实际出现情况,调整窗口的开始位置,确保窗口内的单词频率与 words 中的单词频率相匹配。

3. 实现细节

  • 初始化: 计算每个单词的长度 wordLength,所有单词的数量 wordCount,以及应搜索的窗口大小 windowSize
  • 遍历: 遍历字符串 s 的每个可能的起始位置,步长为 wordLength
  • 内部循环: 对每个起始位置,向右滑动窗口,每次移动一个单词的长度,直到窗口尾部超出字符串 s 的边界。
  • 检查与调整: 每次窗口滑动后,更新当前单词在窗口中的计数,并与 words 字典进行比较,如果当前单词计数超过了应有的频率,则调整窗口的左边界,直至窗口内的单词频率再次符合要求。
  • 记录结果: 如果窗口大小达到了 windowSize,且窗口内的单词与 words 中的单词完全匹配,则记录当前窗口的起始位置。

代码实现

class Solution {
public:vector<int> findSubstring(string s, vector<string>& words) {vector<int> indices;if (s.empty() || words.empty())return indices;int wordLength = words[0].size();int wordCount = words.size();int windowSize = wordLength * wordCount;if (s.size() < windowSize)return indices;// 记录words中每个单词出现的次数unordered_map<string, int> wordMap;for (const string& word : words) {++wordMap[word];}// 检查每个可能的开始位置for (int i = 0; i < wordLength; ++i) {int left = i;int right = i;unordered_map<string, int> currentMap;while (right + wordLength <= s.size()) {string word = s.substr(right, wordLength);right += wordLength;if (wordMap.find(word) != wordMap.end()) {++currentMap[word];// 处理单词出现次数过多的情况while (currentMap[word] > wordMap[word]) {string leftWord = s.substr(left, wordLength);--currentMap[leftWord];left += wordLength;}// 检查是否形成了一个有效的窗口if (right - left == windowSize) {indices.push_back(left);string leftWord = s.substr(left, wordLength);--currentMap[leftWord];left += wordLength;}} else {currentMap.clear();left = right;}}}return indices;}
};

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

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

相关文章

MySQL Workbench支持哪些数据库版本的连接?

MySQL Workbench支持哪些数据库版本的连接&#xff1f; MySQL Workbench 是一款强大的数据库管理和设计工具&#xff0c;它支持连接多种版本的 MySQL 数据库。包括但不限于&#xff1a; MySQL 官方发行的所有版本&#xff0c;从 MySQL 5.0 到最新的 MySQL 8.x 和更高版本。 M…

Linux - 札记 - W10: Warning: Changing a readonly file

Linux - 札记 - W10: Warning: Changing a readonly file 这里写目录标题 一、问题描述1. 现象2. 原因 二、解决方案 一、问题描述 1. 现象 在使用 vim 编辑文件时&#xff08;我这里是要编辑 /root/.ssh/authorized_keys&#xff09;提示&#xff1a;W10: Warning: Changing…

【论文+代码|已完结】基于人工智能的图像识别技术在医疗诊断中的应用

基于人工智能的图像识别技术在医疗诊断中的应用 摘要&#xff1a;随着人工智能技术的飞速发展&#xff0c;图像识别技术在医疗领域的应用日益广泛。本毕业设计旨在研究基于人工智能的图像识别技术在医疗诊断中的应用&#xff0c;通过对大量医疗图像数据的分析和处理&#xff0…

IOS Swift 从入门到精通:ios 连接数据库 安装 Firebase 和 Firestore

创建 Firebase 项目 导航到Firebase 控制台并创建一个新项目。为项目指定任意名称。 在这里插入图片描述 下一步,启用 Google Analytics,因为我们稍后会用到它来发送推送通知。 在这里插入图片描述 在下一个屏幕上,选择您的 Google Analytics 帐户(如果已创建)。如果没…

<电力行业> - 《第7课:发电》

1 发电的原理 电力生产的发电环节是利用电能生产设备将各种一次能源或其他形式的能转换为电能。生产电能的主要方式有火力发电、水力发电、核能发电、地热发电、风力发电、太阳能发电、潮汐能发电、生物智能发电和燃料电池发电等。 除太阳能发电的光伏电池技术和燃料电池发电…

c++ 子类继承父类

这个是子类继承父类 是否重写从父类那里继承来的函数 这个例子的路径 E盘 demo文件夹 fatherChildfunc

蓝卓出席“2024C?O大会”,探讨智能工厂建设新路径

6月29日&#xff0c;“2024C?O大会”在金华成功举办。此次大会由浙江省企业信息化促进会主办&#xff0c;与以往CIO峰会不同&#xff0c;“C?O”代表了企业数字化中的核心决策者群体&#xff0c;包括传统的CIO、CEO、CDO等。 本次大会围绕C?O、AIGC与制造业、数据价值、未来…

统计信号处理基础 习题解答11-9

一个飞行器开始于一个未知位置(, )&#xff0c;按照 以常速运动&#xff0c;其中, 分别是飞行器在x、y方向的速度分量,都是未知的。我们希望估计每一时刻, 飞行器的位置和速度。尽管初始位置(, )和速度, 都是未知的,但是它们可以看成一个随机矢量。证明能够由MMSE估计器估计为 …

libarclite_iphonesimulator.a‘; try increasing the minimum deployment target

1. Xcode 15 编译出现以下错误 clang: error: SDK does not contain libarclite at the path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a; try increasing the minimum deployment ta…

React+TS前台项目实战(二十一)-- Search业务组件封装实现全局搜索

文章目录 前言一、Search组件封装1. 效果展示2. 功能分析3. 代码详细注释4. 使用方式 二、搜索结果展示组件封装1. 功能分析2. 代码详细注释 三、引用到文件&#xff0c;自行取用总结 前言 今天&#xff0c;我们来封装一个业务灵巧的组件&#xff0c;它集成了全局搜索和展示搜…

spring如何给bean动态取不同的别名

开源项目SDK&#xff1a;https://github.com/mingyang66/spring-parent 个人文档&#xff1a;https://mingyang66.github.io/raccoon-docs/#/ spring、springboot向容器中注入bean的时候一般情况下只有一个别名&#xff0c;在某些特殊场景需要指定多个别名。 方案一&#xff1a…

v-if 和 v-show 的含义、使用方式及使用时的区别

学习内容&#xff1a; v-if 和 v-show 的含义、使用方式及使用时的区别&#xff1a; 例如&#xff1a; v-if 的含义v-if 的用法v-show 的含义v-show 的用法v-if 与 v-show 区别 知识小结&#xff1a; 小结 1、v-if v-if 是一种条件性地渲染元素的指令。当条件为真时&#…

ic基础|功耗篇04:门级低功耗技术

大家好&#xff0c;我是数字小熊饼干&#xff0c;一个练习时长两年半的IC打工人。我在两年前通过自学跨行社招加入了IC行业。现在我打算将这两年的工作经验和当初面试时最常问的一些问题进行总结&#xff0c;并通过汇总成文章的形式进行输出&#xff0c;相信无论你是在职的还是…

【chatgpt】npy文件和npz文件区别

npy文件和npz文件都是用于存储NumPy数组的文件格式。它们的主要区别如下&#xff1a; npy文件&#xff1a;这种文件格式用于存储单个NumPy数组。它是一种简单的二进制文件格式&#xff0c;可以快速地读写NumPy数组。 npz文件&#xff1a;这种文件格式是一个压缩包&#xff0c;…

《Windows API每日一练》6.2 客户区鼠标消息

第五章已经讲到&#xff0c;Windows只会把键盘消息发送到当前具有输入焦点的窗口。鼠标消息则不同&#xff1a;当鼠标经过窗口或在窗口内被单击&#xff0c;则即使该窗口是非活动窗口或不带输入焦点&#xff0c; 窗口过程还是会收到鼠标消息。Windows定义了 21种鼠标消息。不过…

UE5蓝图快速实现打开网页与加群

蓝图节点&#xff1a;启动URL 直接将对应的网址输入&#xff0c;并使用即可快速打开对应的网页&#xff0c;qq、discord等群聊的加入也可以直接通过该节点来完成。 使用后会直接打开浏览器。

第11章 规划过程组(收集需求)

第11章 规划过程组&#xff08;一&#xff09;11.3收集需求&#xff0c;在第三版教材第377~378页&#xff1b; 文字图片音频方式 第一个知识点&#xff1a;主要输出 1、需求跟踪矩阵 内容 业务需要、机会、目的和目标 项目目标 项目范围和 WBS 可…

【强化学习】第01期:绪论

笔者近期上了国科大周晓飞老师《强化学习及其应用》课程&#xff0c;计划整理一个强化学习系列笔记。笔记中所引用的内容部分出自周老师的课程PPT。笔记中如有不到之处&#xff0c;敬请批评指正。 文章目录 1.1 概述1.2 Markov决策过程1.2.1 Markov Process (MP) 马尔科夫过程1…

(五)SvelteKit教程:错误页和重定向

&#xff08;五&#xff09;SvelteKit教程&#xff1a;错误页和重定向 设置404页面和重定向非常容易&#xff0c;我们还是在 /about 目录下学习这个知识&#xff0c;文件结构如下&#xff1a; ├── layout.svelte ├── page.svelte ├── about │ └── [aboutID] │…

基于深度学习的人脸关键点检测

1. 任务和目标 人脸关键点检测的主要任务是识别并定位人脸图像中的特定关键点&#xff0c;例如眼睛的角点、眉毛的顶点、鼻子的底端、嘴角等。这些关键点不仅能提供面部结构的几何信息&#xff0c;还可以用于分析表情、识别个体&#xff0c;甚至检测面部姿势。 2. 技术和方法…