算法求解(C#)-- 寻找包含目标字符串的最短子串算法
1. 引言
在字符串处理中,我们经常需要从一个较长的字符串中找到包含特定目标字符串的最短子串。这个问题在文本搜索、基因序列分析等领域有着广泛的应用。本文将介绍一种高效的算法来解决这个问题。
2. 问题描述
给定一个源字符串 source 和一个目标字符串 target,我们需要找到 source 中包含 target 所有字符的最短子串。如果找不到这样的子串,则返回空字符串。问题来源:炼码 32 · 最小子串覆盖
样例
样例 1:
输入:source = “abc” ;target = “ac”
输出:“abc”
解释:“abc” 是 source 的包含 target 的每一个字符的最短的子串。
样例 2:
输入:source = “adobecodebanc” ;target = “abc”
输出:“banc”
解释:“banc” 是 source 的包含 target 的每一个字符的最短的子串。
样例 3:
输入:source = “abc” ; target = “aa”
输出:“”
解释:没有子串包含两个 ‘a’。
3. 算法思路
为了解决这个问题,我们可以使用滑动窗口(Sliding Window)技术。滑动窗口是一种在数组或字符串上处理问题的有效方法,它可以在一次遍历中解决多个连续子数组或子字符串的问题。
步骤:
1、初始化:
- 创建一个字典 targetCount 来记录 target 中每个字符的出现次数。
- 创建一个字典 windowCount 来记录当前窗口中每个字符的出现次数。
- 初始化两个指针 left 和 right,分别表示窗口的左右边界。
- 初始化变量 matched 来记录当前窗口中已经匹配的 target 中的字符种类数。
- 初始化变量 minStart 和 minLength 来记录最短子串的起始位置和长度。
2、扩展窗口:
- 使用 right 指针向右移动,将字符添加到窗口中。
- 更新 windowCount 和 matched。
3、缩小窗口:
- 当窗口包含了 target 中的所有字符时(即 matched == targetCount.Count),尝试缩小窗口以找到更短的子串。
- 使用 left 指针向左移动,从窗口中移除字符。
- 更新 windowCount 和 matched。
- 如果缩小后的窗口仍然包含 target 中的所有字符,并且长度更短,则更新 minStart 和 minLength。
4、返回结果:
- 根据 minStart 和 minLength 从 source 中提取最短子串并返回。
4. 算法实现
以下是该算法的 C# 实现:
using System;
using System.Collections.Generic;class Program
{static void Main(){string source = "adobecodebanc";string target = "abc";string result = FindShortestSubstringContainingTarget(source, target);Console.WriteLine(result); // Output: "banc"}static string FindShortestSubstringContainingTarget(string source, string target){if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(target))return string.Empty;Dictionary<char, int> targetCount = new Dictionary<char, int>();foreach (char c in target){targetCount[c] = 0;}foreach (char c in target){targetCount[c]++;}int left = 0, right = 0;int minStart = 0, minLength = int.MaxValue;int matched = 0;Dictionary<char, int> windowCount = new Dictionary<char, int>();while (right < source.Length){char rightChar = source[right];if (targetCount.ContainsKey(rightChar)){if (!windowCount.ContainsKey(rightChar))windowCount[rightChar] = 0;windowCount[rightChar]++;if (windowCount[rightChar] == targetCount[rightChar])matched++;}while (matched == targetCount.Count){if (right - left + 1 < minLength){minStart = left;minLength = right - left + 1;}char leftChar = source[left];if (targetCount.ContainsKey(leftChar)){windowCount[leftChar]--;if (windowCount[leftChar] < targetCount[leftChar])matched--;}left++;}right++;}return minLength == int.MaxValue ? string.Empty : source.Substring(minStart, minLength);}
}
输出结果
5. 示例分析
假设 source = “adobecodebanc”,target = “abc”。
初始时,left = 0,right = 0,matched = 0,minStart = 0,minLength = int.MaxValue。
随着 right 的移动,窗口逐渐扩展,直到包含 target 中的所有字符。
当窗口包含 abc 时(例如,当 right 指向 c 时),开始缩小窗口。
在缩小窗口的过程中,找到包含 abc 的最短子串 “banc”。
6. 结论
本文介绍了一种使用滑动窗口技术来寻找包含目标字符串的最短子串的算法。该算法通过维护一个窗口来动态地包含和排除字符,从而在一次遍历中找到了最短子串。这种方法不仅高效,而且易于理解和实现。
相关文章:

算法求解(C#)-- 寻找包含目标字符串的最短子串算法
1. 引言 在字符串处理中,我们经常需要从一个较长的字符串中找到包含特定目标字符串的最短子串。这个问题在文本搜索、基因序列分析等领域有着广泛的应用。本文将介绍一种高效的算法来解决这个问题。 2. 问题描述 给定一个源字符串 source 和一个目标字符串 targe…...

AscendC从入门到精通系列(二)基于Kernel直调开发AscendC算子
本次主要讨论下AscendC算子的开发流程,基于Kernel直调工程的算子开发。 1 AscendC算子开发的基本流程 使用Ascend C完成Add算子核函数开发; 使用ICPU_RUN_KF CPU调测宏完成算子核函数CPU侧运行验证; 使用<<<>>>内核调用符…...

DAO模式的理解
目录 DAO模式 含义 DAO模式 的理解 分层思维 分层含义 分层目的 dao层 dao包(对接的是操作数据库的接口) dao包下lmpl 包(dao包中接口的实现类) 补充 1 你创建的实体类需要和数据库中建的表一一对应。 总结 DAO模式 含义…...

使用GitHub Actions实现CI/CD流程
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 使用GitHub Actions实现CI/CD流程 GitHub Actions 简介 创建仓库 配置工作流 示例工作流文件 触发和运行工作流 部署应用 最佳实…...

机器人助力Bridge Champ游戏:1.4.2版本如何提升玩家体验
在Bridge Champ游戏中,机器人扮演着桥牌游戏的“无名英雄”角色,默默地提升玩家体验。凭借智能化的设计,这些机器人不仅能够陪练,也大大提升了比赛的流畅度与趣味性。 Bridge Champ是什么 Bridge Champ是一个基于Ignis公链的在线…...

滑动窗口(单调队列维护窗口)-acwing
题目: 154. 滑动窗口 - AcWing题库 代码(删除队列窗口多余的>单调队列) 判断最值是否滑出窗口可以放在 入队的后面。 但是,判断,准备入队元素比前面小,要从队尾出队,放在入队前。 总之&a…...

ALB搭建
ALB: 多级分发、消除单点故障提升应用系统的可用性(健康检查)。 海量微服务间的高效API通信。 自带DDoS防护,集成Web应用防火墙 配置: 1.创建ECS实例 2.搭建应用 此处安装的LNMP 3.创建应用型负载均衡ALB实例 需要创建服务关联角…...

c# 动态lambda实现二级过滤(支持多种参数类型和模糊查询)
效果 调用方法 实体类(可以根据需求更换) public class ToolStr50 {public bool isSelected { get; set; }public string toolStr1 { get; set; }public string toolStr2 { get; set; }public string toolStr3 { get; set; }public string toolStr4 { …...

第J5周:DenseNet+SE-Net实战
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 任务: ●1. 在DenseNet系列算法中插入SE-Net通道注意力机制,并完成猴痘病识别 ●2. 改进思路是否可以迁移到其他地方呢 ●3. 测试集acc…...

Intern大模型训练营(五):书生大模型全链路开源体系笔记
观看视频,可以比较详细地了解到书生大模型全链路开源体系。 其中有几个印象比较深的点: 这张图讲述了书生浦语大模型开源的发展史,同时与主流的llama和Chatgpt模型进行比较,可以看出在参数上,InterLM在努力追赶甚至超…...

聚观早报 | 比亚迪腾势D9登陆泰国;苹果 iOS 18.2 将发布
聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 11月5日消息 比亚迪腾势D9登陆泰国 苹果 iOS 18.2 将发布 真我GT7 Pro防尘防水细节 小米15 Ultra最快明年登场 …...

微信小程序开发,诗词鉴赏app,诗词搜索实现(三)
微信小程序开发,诗词鉴赏app(一): https://blog.csdn.net/jky_yihuangxing/article/details/143501681微信小程序开发,诗词鉴赏app,诗词推荐实现(二):https://blog.csdn.net/jky_yih…...

Kotlin 协程使用及其详解
Kotlin协程,好用,但是上限挺高的,我一直感觉自己就处于会用,知其然不知其所以然的地步。 做点小总结,比较浅显。后面自己再继续补充吧。 一、什么是协程? Kotlin 协程是一种轻量级的并发编程方式&#x…...

计算机组成原理--三章四章
这里写目录标题 第三章:存储系统3.1 存储系统基本概念引入存储器的层次结构简介产品 存储器的分类按层次分类按照介质分类按照存取方式分类按照信息的可更改性按照信息的可保护性 存储器的性能指标存储容量单位成本存储速度 总结 3.2主存储器的基本组成半导体元器件…...

单片机工程使用链接优化-flto找不到定义_链接静态库
IDE: CLion HOST: Windows 11 MinGW:x86_64-14.2.0-release-posix-seh-ucrt-rt_v12-rev0 GCC: arm-gnu-toolchain-13.3.rel1-mingw-w64-i686-arm-none-eabi 示例工程:https://github.com/ichliebedich-DaCapo/STM…...

UniTask/Unity的PlayerLoopTiming触发顺序
开始尝试在项目中使用UniTask,发现其中的UniTask.Yield确实很好用,还可以传入PlayerLoopTiming来更细致的调整代码时机,不过平常在Mono中接触的只有Awake,Start,Update等常用Timing,其他的就没怎么接触了&a…...

【报错记录】Steam迁移(移动)游戏报:移动以下应用的内容失败:XXX: 磁盘写入错误
前言 由于黑神话悟空,导致我的2TB的SSD系统盘快满了,我又买了一块4TB的SSD用来存放游戏,我就打算把之前C盘里的游戏移动到D盘,结果Steam移动游戏居然报错了,报的还是“磁盘写入错误”,如下图所示ÿ…...

C 语言学习-04【结构化程序设计】
1、单分支结构语句 用单分支结构进行奇偶判断: #include <stdio.h>int main() {int num;printf("Please enter an integer: ");scanf("%d", &num);if (num % 2 ! 0) {printf("%d is odd! \n", num);}if (num % 2 0) {prin…...

机器视觉:轮廓匹配算法原理
轮廓匹配的模板变量主要包括模板图像(Template)和待检测图像(Source Image) 在轮廓匹配中,模板变量主要包括一下几个关键部分: 模板图像(Template):这是进行匹配的…...

动力商城-02 环境搭建
1.父工程必须满足:1.1删除src目录 1.2pom 2.依赖继承 //里面的依赖,后代无条件继承<dependencies></dependencies>//里面的依赖,后代想要继承,得自己声明需要使用,可以不写版本号,自动继承&l…...

【react】Redux基础用法
1. Redux基础用法 Redux 是一个用于 JavaScript 应用的状态管理库,它不依赖于任何 UI库,但常用于与 React 框架配合使用。它提供了一种集中式的状态管理方式,将应用的所有状态保存在一个单一的全局 Store(存储)中&…...

使用Python分析股票价格数据并计算移动平均线的实用指南
使用Python分析股票价格数据并计算移动平均线的实用指南 在金融市场中,移动平均线(Moving Average, MA)是一种常用的技术分析工具,用于平滑价格数据,帮助投资者识别趋势。本文将详细介绍如何使用Python分析股票价格数据,并计算移动平均线。我们将通过一个实际的案例来演…...

如何解决FPS低的问题?代码优化方法有哪些?
如果你是一名游戏开发者,或者对电脑性能有所追求的用户,那么你一定遇到过帧率(FPS)低的问题。帧率低会导致游戏卡顿、画面不流畅等问题,极大地影响了用户体验。本文将从代码层面探讨FPS低的原因,并提供一些…...

QT信号和槽与自定义的信号和槽
QT信号和槽与自定义的信号和槽 1.概述 这篇文章介绍下QT信号和槽的入门知识,通过一个案例介绍如何创建信号和槽,并调用他们。 2.信号和槽使用 下面通过点击按钮关闭窗口的案例介绍如何使用信号和槽。 创建按钮 在widget.cpp文件中创建按钮代码如下 …...

LC:二分查找——杂记
文章目录 268. 丢失的数字162. 寻找峰值 268. 丢失的数字 LC将此题归类为二分查找,并且为简单题,下面记一下自己对这道题目的思考。 题目链接:268.丢失的数字 第一次看到这个题目,虽然标注的为简单,但肯定不能直接排…...

GA/T1400视图库平台EasyCVR多品牌摄像机视频平台前端监控摄像头镜头的基础知识
在现代安全监控系统中,摄像机镜头作为捕捉图像的关键组件,其选择和应用直接影响到监控图像的质量和系统的整体性能。随着技术的发展,摄像机镜头的种类和功能也在不断扩展,以适应各种复杂的监控环境和需求。对于相机成像来讲&#…...

【C++】踏上C++的学习之旅(六):深入“类和对象“世界,掌握编程的黄金法则(一)
文章目录 前言1. "面向过程"和"面向对象"的碰撞1.1 面向过程1.2 面向对象 2. "类"的引入3. "类"的定义3.1 🍉语法展示:3.2 "类"的两种定义方式3.3 "类"的命名规则 4. 类的访问限定符以及封…...

【物联网技术】ESP8266 WIFI模块在STA模式下作为TCP客户端上电自动进入透传数据模式
前言:讲解如何在ESP8266 WIFI模块在STA模式下作为TCP客户端与网络调试助手(TCP服务器)上电自动进入透传数据模式,而不需重新再发指令配置进入透传模式。 演示视频: ESP8266 WIFI模块在STA模式下作为TCP客户端上电自动进入透传数据模式 wifi模块在STA模式下作为TCP客户端相…...

重构代码之用委托替代继承
在代码重构中,用委托替代继承 是一种用于改善代码设计和提高灵活性的重要技术。它的核心思想是,将子类与父类的直接继承关系转换为委托关系,即子类不再直接继承父类,而是通过持有父类的实例来访问所需的功能。 一、为什么需要用委…...

软件设计师下午题UML15分
一、涉及到的图及对应关系 二、例题 1.用例图和类图的例题 解析及答案 2.状态图和类图的例题 3.通信图和类图例题 例题...