目录
一.滑动窗口的算法模板:
1.模板一:
#include <iostream>
#include <unordered_map>
using namespace std;
string minWindow(string s, string t) {
// 记录最短子串的开始位置和长度
int start = 0, minLen = INT_MAX;
int left = 0, right = 0;
unordered_map<char, int> window;
/*首先unordered_map是一个将key和value关联起来的容器,
它可以高效的根据单个key值查找对应的value.
key值应该是唯一的,key和value的数据类型可以不相同。
unordered_map存储元素时没有进行排序,只是根据key的哈希值,将元素存在指定位置,
所以根据key查找单个value时非常高效,平均可以在常数时间内完成。
unordered_map查询单个key的时候效率比map高,但是要查询某一范围内的key值时比map效率低。
可以使用[]操作符来访问key值对应的value值。
*/
unordered_map<char, int> needs;//默认值为0;
for (char c : t) needs[c]++;
/**相当于C++的:
for (int i = 0; i < s.length(); i++)
{
s[i]....
}*/
int match = 0;
while (right < s.size()) {
char c1 = s[right];
if (needs.count(c1)) {/*map和set两种容器的底层结构都是红黑树,
所以容器中不会出现相同的元素,因此count()的结果只能为0和1,
可以以此来判断键值元素是否存在(当然也
可以使用find()方法判断键值是否存在)。*/
window[c1]++;
if (window[c1] == needs[c1])
match++;
}
right++;
while (match == needs.size()) {
if (right - left < minLen) {
// 更新最小子串的位置和长度
start = left;//用star来标记最短字符串的位置,minlen则是它的长度
minLen = right - left;
}
char c2 = s[left];
if (needs.count(c2)) {
window[c2]--;//c2个数--
if (window[c2] < needs[c2])
match--;//匹配成功的字符数目减1;然后跳出循环
}
left++;//窗口继续向左滑动
}
}
return minLen == INT_MAX ?
"" : s.substr(start, minLen);
/* string,包含s中从pos开始的len个字符的拷贝(pos的默认值是0,len的默认值是s.size() - pos,
即不加参数会默认拷贝整个s)
异常 :若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,
则substr会调整n的值,只拷贝到string的末尾
*/
}
int main01() {
string s, t;
cin>>s>>t;
string temp = minWindow(s, t);
if (temp == "") cout << "您要查找的子串不存在" << endl;
else cout << "包含目标字符串的最小子串为" << temp << endl;
return 01;
}
借鉴资料: