【算法随笔: 76 最小覆盖子串】(leetcode | hash | 变长滑动窗口 | 预处理优化)

题目描述:

给你一个字符串 s 、一个字符串 t返回 s 中涵盖 t 所有字符的最小子串(子串指排放连续的子序列)。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

 

 

/*最小覆盖子串*/

#include <string>
#include <unordered_map>
#include <limits>
#include <vector>

std::string minimal_hash_covering_substring(std::string const & s, std::string const & p){
	int s_length { static_cast<int>(s.length()) };
	int p_length { static_cast<int>(p.length()) };
	if(s_length < p_length) return std::string {};
	std::vector<std::pair<int, char>> shrinks {};
	shrinks.reserve(s_length << 1 | 1);
	std::unordered_map<char, int> needed {};
	for(auto const & c : p) (void) needed[c] ++;
	int different { static_cast<int>(needed.size()) };
	for(int i {}; i < s_length; ++i) if(needed.count(s[i])) shrinks.emplace_back(i, s[i]);
	std::unordered_map<char, int> hash {};
	int first {};
	int last {};
	int start {};
	int validates {};
	int result { std::numeric_limits<int>::max() };
	while(! (last == s_length)){
		auto last_char { shrinks[last ++].first };
		++ hash[last_char];
		if(hash.count(last_char) == needed.count(last_char)) ++ validates;
		while(validates == different){
			auto current_length { shrinks[last - 1].second - shrinks[first].second + 1 };
			if(current_length < result){
				result = current_length;
				start = shrinks[first].second;
			}
			auto first_char { shrinks[first ++].first };
			if(hash.count(first_char) == needed.count(first_char)) -- validates;
			-- hash[first_char];
		}
	}
	return result == std::numeric_limits<int>::max() ? std::string {} : s.substr(start, result);
}

 

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值