滑动窗口算法:找出最小覆盖子串(Python实现)

题目

给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"

Python实现

import sys


def longest_dup_substr(s, t):
    # 构造需要匹配t的字符串的数量字典
    need_map = {}
    for c in t:
        need_map[c] = need_map.get(c, 0) + 1

    # 记录窗口已经匹配的字符串数量
    window_map = {}
    # 记录已经满足need_map的数量
    match_cnt = 0

    # 需要匹配的数量和已经匹配的数量
    need_cnt = len(need_map)

    left = 0  # 窗口左边界
    right = 0  # 窗口边右界

    start = 0  # 记录匹配的起点
    min_len = sys.maxsize  # 记录匹配的最小距离

    while right < len(s):
        c = s[right]
        # 如果匹配
        if c in need_map:
            # 更新窗口匹配字符数量
            window_map[c] = window_map.get(c, 0) + 1
            # 如果该字符串数量达标,更新match_cnt
            if window_map[c] == need_map[c]:
                match_cnt += 1

        # 右移窗口
        right += 1

        # 如果全部数量达标,收缩窗口,并更新起点和距离
        while match_cnt == need_cnt:
            if right - left < min_len:
                start = left  # 记录匹配的起点
                min_len = right - left  # 记录匹配的最小距离
            # 定位左边要移除的字符
            d = s[left]
            # 如果在匹配的字符里,更新窗口,减少匹配数量
            if d in window_map:
                if window_map[d] == need_map[d]:
                    match_cnt -= 1
                window_map[d] -= 1

            # 收缩左边窗口
            left += 1

    # 没匹配到,返回空字符串
    if min_len == sys.maxsize:
        return ""

    return s[start:start + min_len]


s = "ADOBECODEBANC"
t = "ABC"
res = longest_dup_substr(s, t)
print(res)

posted @ 2021-07-28 17:28  雪山飞猪  阅读(379)  评论(0编辑  收藏  举报