📌  相关文章
📜  在包含另一个字符串的所有字符的字符串中找到最小的窗口 - C++ (1)

📅  最后修改于: 2023-12-03 15:37:40.579000             🧑  作者: Mango

在包含另一个字符串的所有字符的字符串中找到最小的窗口 - C++

在字符串处理过程中,我们常常会遇到需要在一个较长的字符串中找到包含另一个字符串的最小窗口的问题。例如在搜索引擎中,我们需要从大量文本中找到最匹配某个关键词的文本段,这时就需要我们找到最小的包含该关键词的文本窗口。下面介绍一种基于滑动窗口的解决方案。

解决方案

我们可以使用两个指针来构建一个滑动窗口,通过移动右指针来不断扩大窗口,当窗口包含所有所需的字符后,再移动左指针缩小窗口,直到得到最小窗口。具体步骤如下:

  1. 创建两个指针,左指针start和右指针end,都指向字符串的第一个字符。

  2. 移动右指针end,直到窗口包含了所有所需的字符。

  3. 移动左指针start,缩小窗口,直到不能再缩小为止。

  4. 记录当前窗口大小,并更新最小窗口大小。

  5. 重复2~4步骤,直到右指针到达字符串的末尾。

代码实现

下面是C++实现代码:

string minWindow(string s, string t) {
    unordered_map<char, int> needs, window;  // needs存储需要匹配的字符及其出现次数,window存储当前窗口中包含的字符及其出现次数
    for (char c : t) needs[c]++;  // 初始化needs
    int left = 0, right = 0;  // 左右指针
    int valid = 0;  // 当前窗口中已经有多少个需要匹配的字符
    int start = 0, len = INT_MAX;  // 记录最小窗口的起始位置和长度
    while (right < s.size()) {
        char c = s[right];  // 右移右指针
        right++;
        if (needs.count(c)) {  // 如果当前字符是需要匹配的字符
            window[c]++;  // 将当前字符加入窗口
            if (window[c] == needs[c])  // 如果窗口中该字符已经满足需要匹配的次数
                valid++;  // 匹配成功的字符数+1
        }
        while (valid == needs.size()) {  // 如果当前窗口已经包含了所有需要匹配的字符
            if (right - left < len) {  // 更新最小窗口的位置和长度
                start = left;
                len = right - left;
            }
            char d = s[left];  // 左移左指针
            left++;
            if (needs.count(d)) {  // 如果移动后的字符是需要匹配的字符
                if (window[d] == needs[d])  // 如果该字符已经匹配成功
                    valid--;  // 匹配成功的字符数-1
                window[d]--;  // 从窗口中移除该字符
            }
        }
    }
    return len == INT_MAX ? "" : s.substr(start, len);  // 返回最小窗口
}
总结

滑动窗口是一种可行的解决字符串匹配问题的算法,它的核心思想是通过移动两个指针来构建一个窗口,通过不断移动窗口的左右边界来寻找最优解。虽然使用滑动窗口算法能够很大程度上提高字符串匹配的效率,但在实际应用中仍需根据具体情况选择合适的算法和实现方式。