最左侧冗余覆盖子串
题目描述
给定两个字符串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只包含小写字母.
备注:
0 ≤ len(s1) ≤ 1000000
0 ≤ len(s2) ≤ 20000000
0 ≤ k ≤ 1000
输出描述
最左侧的s2以长度k冗余覆盖s1的子串首个元素下标, 如果没有返回 -1
.
示例1
输入:
ab
aabcd
1
输出:
0
说明: 子串aab和abc符合要求, 由于aab在abc的左侧, 因此输出aab的下标 0
.
示例2
输入:
abc
dfs
10
输出:
-1
题解
Python
import string
def solution():
# 读取输入
s1 = input()
s2 = input()
k = int(input())
assert 0 < k
# 统计s1中各个字母出现的次数
s1_chars = dict((char, 0) for char in string.ascii_lowercase)
for char in s1:
s1_chars[char] += 1
# 滑动窗口内各个字母出现的次数
window_chars = dict((char, 0) for char in string.ascii_lowercase)
left = 0
right = 0
s1_chars_left = len(s1)
while right < len(s2):
# 更新窗口内各个字母的次数
right_char = s2[right]
window_chars[right_char] += 1
if window_chars[right_char] <= s1_chars[right_char]:
s1_chars_left -= 1
# 如果窗口太大, 将窗口左侧向右移
if right - left + 1 > len(s1) + k:
left_char = s2[left]
if window_chars[left_char] <= s1_chars[left_char]:
s1_chars_left += 1
# 将左侧字符从窗口字母计数中移除
window_chars[left_char] -= 1
left += 1
# 如果 s1 中没有剩下的字符待检查, 就说明找到了子串
if s1_chars_left == 0:
return left
# 将窗口右侧向右移
right += 1
return -1
def main():
ans = solution()
print(ans)
if __name__ == "__main__":
main()