只需要再窗口移动的时候,考虑变化的部分,这样可以减少每次计算的内容
# 给定两个字符串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 删除。