寻找符合要求的最长子串

题目描述

给定一个字符串s, 找出这样一个子串:

  • 该子串中任意一个字符最多出现2次
  • 该子串不包含指定某个字符

请你找出满足该条件的最长子串的长度.

输入描述

  • 第一行:要求不包含的指定字符, 为单个字符, 取值范围[0-9a-zA-Z]
  • 第二行:字符串s, 每个字符范围[0-9a-zA-Z], 长度范围[1, 10000]

输出描述

  • 第一行: 要求不包含的指定字符, 为单个字符, 取值范围[0-9a-zA-Z]
  • 第二行: 字符串s, 每个字符范围[0-9a-zA-Z], 长度范围[1, 10000]

示例1

输入:

D
ABC123

输出:

6

示例2

输入:

D
ABACA123D

输出:

7

题解

Python

from collections import defaultdict

def main():
    # 先读取输入值
    ignored_char = input()
    s = input()
    assert len(ignored_char) == 1
    assert 1 <= len(s) <= 10000

    # 使用滑动窗口遍历字符串s中的所有字符
    # 使用字典来统计各个字符出现的次数
    # 当窗口右侧向右移动时, 将新的字符加到到计数字典中
    # 当窗口左侧向右移动时, 将左侧旧的字符从计数字典中减1
    # 判定条件有两个:
    #   1. 不能出现 ignored_char
    #   2. 窗口中同一个字符最大出现次数是2次
    
    # 窗口中各字符的计数
    window_chars = defaultdict(int)

    left = 0
    right = 0
    substring_max_len = 0
    # 窗口中同一个字符最大出现次数是2次
    char_max_presents = 2

    # 遍历字符串s
    while right < len(s):
        right_char = s[right]

        # 如果窗口右侧出现了禁止的字符, 就说明这个窗口要被终止了
        if right_char == ignored_char:
            substring_max_len = max(substring_max_len, right - left)
            # 将左右指针都移动到下一个字符
            right += 1
            left = right
            # 重置计数字典
            window_chars.clear()
            continue

        # 将当前字符加入到计数字典中
        window_chars[right_char] += 1

        # 如果当前字符出现次数超过 2 次, 就需要把窗口左侧向右移动
        if window_chars[right_char] > char_max_presents:
            substring_max_len = max(substring_max_len, right - left)
            left_char = s[left]
            while left_char != right_char:
                window_chars[left_char] -= 1
                left += 1
                left_char = s[left]

        # 最后, 将窗口右侧向右移
        right += 1

    # 最后一个子串
    substring_max_len = max(substring_max_len, right - left)

    print(substring_max_len)

if __name__ == "__main__":
    main()