算法求解(C#)-- 寻找包含目标字符串的最短子串算法

news/2024/11/13 15:52:24/

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. 结论

本文介绍了一种使用滑动窗口技术来寻找包含目标字符串的最短子串的算法。该算法通过维护一个窗口来动态地包含和排除字符,从而在一次遍历中找到了最短子串。这种方法不仅高效,而且易于理解和实现。


http://www.ppmy.cn/news/1546713.html

相关文章

新日撸java三百行` 新手小白java学习记录 `Day1

新日撸java三百行新手小白java学习记录 Day1 模拟多线程回调机制 文章目录 新日撸java三百行 新手小白java学习记录 前言一 、模拟异步机制提出问题解决方案 前言 古人称长江为江&#xff0c;黄河为河。长江水清&#xff0c;黄河水浊&#xff0c;长江在流&#xff0c;黄河也在…

cesium 3DTiles之pnts格式详解

Point Cloud 1 概述 点云&#xff08;Point Cloud&#xff09;瓦片格式用于高效流式传输大规模点云数据&#xff0c;常用于 3D 可视化中。每个点由位置&#xff08;Position&#xff09;和可选的属性定义&#xff0c;这些属性用来描述点的外观&#xff08;如颜色、法线等&…

Spring Cloud微服务超详细讲解

Spring Cloud 是一个基于 Spring Boot 的微服务框架&#xff0c;它提供了一系列工具和服务来帮助开发者构建和管理微服务架构。以下是一个超级详细的讲解&#xff0c;涵盖了 Spring Cloud 的核心概念、组件以及如何构建一个简单的微服务应用。 1. 微服务架构概述 什么是微服务…

【开源免费】基于SpringBoot+Vue.JS医疗病历交互系统(JAVA毕业设计)

博主说明&#xff1a;本文项目编号 T 072 &#xff0c;文末自助获取源码 \color{red}{T072&#xff0c;文末自助获取源码} T072&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

Java从入门到精通笔记篇(十二)

枚举类型与泛型 枚举类型可以取代以往常量的定义方式&#xff0c;即将常量封装在类或接口中 使用枚举类型设置常量 关键字为enum 枚举类型的常用方法 values()方法 枚举类型实例包含一个values()方法&#xff0c;该方法将枚举中所有的枚举值以数组的形式返回。 valueOf()可…

初始化mysql5.7

-- 环境变量 MYSQL_HOME %MYSQL_HOME%\bin -- 新增配置文件 my.ini [mysqld] port 3306 basedir D:/develop/MySQL/mysql-5.7.44-winx64 datadir D:/develop/MySQL/mysql-5.7.44-winx64/data max_connections 200character-set-serverutf8 default-storage-engineINNODB …

科研绘图系列:R语言差异分析双侧柱状图(grouped barplot)

文章目录 介绍加载R包数据画图系统信息介绍 双侧柱状图(grouped barplot),也称为分组柱状图,是一种用于展示不同组别之间比较的数据可视化图表。它通过将不同组别的柱状图并排放置,可以直观地比较不同组在各个类别上的表现或特征。以下是双侧柱状图的一些关键特点和用途:…

VBA高级应用30例应用3在Excel中的ListObject对象:插入行和列

《VBA高级应用30例》&#xff08;版权10178985&#xff09;&#xff0c;是我推出的第十套教程&#xff0c;教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开&#xff0c;这套教程案例与理论结合&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以…