滑动窗口解决最小覆盖子串和最长公共子串

最小覆盖子串

问题描述

输出最小覆盖子串:给定一个字符串 abglccoba和一个目标字符串abcc,在给定字符串找到可以覆盖目标字符串所有字符(字符个数也要对应)的最小子串,则预期结果为ccoba

思路

采用滑动窗口的思想

  1. 双指针,初始时,i=j=0,都在字符串的最左边,j向右移动,如果i与j之间的字符满足要求(字符个数可能会大于所需的个数),i向右移动,缩短子串
  2. 如果正好满足要求,记录子串长度,动态记录最小子串起始索引

代码实现

from collections import Counter

s = 'ADOBECODEBANC'
flag = 'ABC'
if len(s) < len(flag):
    print('')
else:
    cnt = Counter(flag)
    need = len(flag) # 目标字符串的个数
    minlen = len(s) + 1
    i = 0
    start, end = 0, -1
    for j in range(len(s)):
        if s[j] in cnt:
            if cnt[s[j]] > 0:
                need -= 1
            cnt[s[j]] -= 1
        while need == 0:
            if minlen > j - i + 1:
                minlen = j - i + 1
                start, end = i, j
            ch_i = s[i]
            if ch_i in cnt:
                if cnt[ch_i] >= 0:
                    need += 1
                cnt[ch_i] += 1
            i += 1
    print(s[start:end+1])


最长公共子串

问题描述

返回两个字符串中最长的公共子串

思路

滑动窗口解决

  1. 遍历短的字符串
  2. 问题在于i的变化,i是左指针
  1. 当前字符若不在长的字符串中,i更新到 j+1
  2. 若当前字符在长的字符串中,且i:j+1的子串不在长字符串中,则i向右移动i+1,直到i:j+1的子串在长字符串中,也就表示直到i:j+1是一个公共子串
  3. 若当前字符在长的字符串中,且i:j+1的子串也在长字符串中,则该子串为一个公共子串,是不是最长需要对比

代码实现

string_1 = input().strip()
string_2 = input().strip()
if len(string_1) >= len(string_2):
    longstring = string_1
    shortstring = string_2
else:
    longstring = string_2
    shortstring = string_1
start, end = 0, -1
maxlen = 0
i = 0
for j in range(len(shortstring)):

    if shortstring[j] not in longstring:
        i = j + 1
        continue

    while shortstring[i:j + 1] not in longstring:
        i += 1
    if shortstring[i:j + 1] in longstring:
        if maxlen < j + 1 - i:
            maxlen = j + 1 - i
            start, end = i, j


print(shortstring[start:end + 1])

"""
输入:
abchbcedwxyzh
abcediwxyzh
"""
>
  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值