1. 程式人生 > 其它 >滑動視窗演算法:找出最小覆蓋子串(Python實現)

滑動視窗演算法:找出最小覆蓋子串(Python實現)

題目

給你一個字串 S、一個字串 T,請在字串 S 裡面找出:包含 T 所有字元的最小子串。
示例:
輸入: S = "ADOBECODEBANC", T = "ABC"
輸出: "BANC"

Python實現

import sys


def longest_dup_substr(s, t):
    need_map = {}
    window_map = {}

    # 構造需要匹配t的字串的數量字典
    for c in t:
        if c not in need_map:
            need_map[c] = 1
        else:
            need_map[c] += 1

    need_cnt = len(need_map)  # 需要匹配的數量
    match_cnt = 0  # 已經匹配的數量

    left = 0  # 視窗左邊界
    right = 0  # 視窗右邊界

    start = 0  # 匹配起點
    min_len = sys.maxsize  # 匹配的距離

    while right < len(s):
        c = s[right]

        # 如果匹配
        if c in need_map:
            # 更新視窗匹配字元數量
            if c not in window_map:
                window_map[c] = 1
            else:
                window_map[c] += 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)