首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >滑动窗口搜索-冗余子串

滑动窗口搜索-冗余子串

原创
作者头像
Swing Dunn
发布2025-11-10 15:25:13
发布2025-11-10 15:25:13
1890
举报
文章被收录于专栏:刷点题15天(一)刷点题15天(一)

只需要再窗口移动的时候,考虑变化的部分,这样可以减少每次计算的内容

代码语言:txt
复制
# 给定两个字符串s1和s2和正整数K,其中s1长度为n1,s2长度为n2,在s2中选一个子串,满足:

# 该子串长度为n1+k
# 该子串中包含s1中全部字母,
# 该子串每个字母出现次数不小于s1中对应的字母,
# 我们称s2以长度k冗余覆盖s1,给定s1,s2,k,求最左侧的s2以长度k冗余覆盖s1的子串的首个元素的下标,如果没有返回-1。

# 输入描述
# 输入三行,第一行为s1,第二行为s2,第三行为k,s1和s2只包含小写字母

# 输出描述
# 最左侧的s2以长度k冗余覆盖s1的子串首个元素下标,如果没有返回-1。

from collections import Counter
s1 = input()
s2 = input()
k = int(input())

# s1 目标子串  s2 搜索的可能存在目标子串的长串   k 冗余窗口长度
def getReult(s1, s2, k):
    n1 = len(s1)
    n2 = len(s2)
    if n2 < n1 + k :
        return -1
    
    count = Counter(s1)

    total  = n1
    maxI = n2 - n1 - k
    n = n1 + k

    #遍历0 -ni+k  即最左边从0开始到起始窗口 在这个窗口中 存在s1中的字母 则total -1  每个字母的统计数 -1
    #如果遍历结束 total刚好为0 则说明s1中出现的所有字母  都在这个窗口中找到了  
    for j in range(n):
        c = s2[j]

        if count.get(c) is not None:
            if count[c] > 0:
                total -= 1
            count[c] -= 1

        if total == 0:
            return 0 
    #滑动窗口 区别只在于增加最右边 去掉最左边的字母  不用反复遍历
    for i in range(1, maxI):
        remove = s2[i-1]
        add = s2[i + n - 1]
    
        #如果最左边移除的这个元素 存在与s1中  则需要将他的计数补充回来
        if count.get(remove) is not None:
            if count[remove] >= 0:
                total +=1
            count[remove] += 1

        #如果最右边补充进来的元素存在与s1中 则将其计数减1
        if count.get(add) is not None:
            if count[add] > 0:
                total -= 1
            count[add] -= 1

        if total == 0:
            return i
    return -1

print(getReult(s1, s2, k))

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档