滑动窗口算法匹配字符子串

696 阅读1分钟

参考:Sliding Window Algorithm(滑动窗口算法)分析与实践

例题:最小覆盖子串

给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。

示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        if len(t) > len(s):
            return ""
        if len(t) is None or len(s) is None:
            return ""
        
        # 计算每个字符的个数和字符串总长度
        t_dict = {}
        ABC = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
        
        count = 0
        for char in ABC:
            n = t.count(char)
            if n > 0:
                t_dict[char] = n
                count += n
        
        # 记录最小的结果的下标和长度
        min_begin = -1
        min_end = -1
        min_num = -1
        
        # 记录s字符串中和t有关的字符的下标
        index = []
        # 记录s字符串中和t有关的字符的值
        strlist = []
        # 临时变量,字符的下标
        i = 0
        
        for char in s:
            if char in t_dict.keys():
                strlist.append(char)
                index.append(i)
            i += 1
            
        # s字符串中和t有关的字符集长度少过t的长度
        # 不可匹配,直接return
        length = len(t)
        # 记录s字符串中和t有关的字符的长度
        str_len = len(strlist)
        if str_len < length:
            return ""
            
        begin = 0
        end = 0 
        max_begin = str_len - length
        
        while end <= str_len and begin <= max_begin:
            isOK = True         # 记录是否成功匹配
            if end - begin < length:
                isOK = False
            else:
                if count > 0 :
                    isOK = False
                else:
                    pass
                
            if isOK:
                # 匹配成功,记录下标和长度
                num = index[end-1] - index[begin]
                if num < min_num or min_num == -1:
                    min_begin = begin
                    min_end = end-1
                    min_num = num
                    
                # 匹配成功,字符串头部指针向前推进
                # 尝试以更短的长度成功匹配
                k = strlist[begin]
                t_dict[k] += 1
                if t_dict[k] > 0:
                    count += 1 
                begin += 1
            else:
                # 匹配没成功,字符串尾部指针向前推进
                if end < str_len:
                    end += 1
                    k = strlist[end - 1]
                    t_dict[k] -= 1
                    if t_dict[k] >= 0:
                        count -= 1 
                else:
                # 最后字符串尾部指针已经指向最后一位字符串
                # 头部指针向前推进直到begin <= max_begin尝试以更短的长度成功匹配
                    k = strlist[begin]
                    t_dict[k] += 1
                    if t_dict[k] > 0:
                        count += 1 
                    begin += 1
        
        # 最后如果匹配成功,就返回结果    
        if min_num != -1:
            start = index[min_begin]
            end = index[min_end] + 1
            return s[start: end]
        else:
            return ""