题目描述
关联子串:给定两个字符串str1和str2,如果字串str1中的字符经过排列组合后的字符串中,只要有一个字符串是str2的子串,则认为str1是str2的关联子串。
返回值:
若str1是str2的关联子串,请返回子串在str2的起始位置;
若不是关联子串,则返回-1。
输入描述
输入两个字符串,分别为题目中描述的str1、str2。
输出描述
若str1是str2的关联子串,请返回子串在str2的起始位置;
若不是关联子串,则返回-1。
若str2中有多个str1的组合子串,请返回最小的起始位置。
提示
- 输入的字符串只包含小写字母;
- 两个字符串的长度范围[1,100000]之间;
用例

题目解析
本题可以用尺取法解决,通过两个指针i和j来遍历数组或字符串。这两个指针分别代表区间的起点和终点。通过移动这两个指针,可以有效地减少算法的时间复杂度,从O(n^2)降低到O(n)。
尺取法,通常是有一个子串str1,和一个父串str2,我们需要在父串str2中找到包含str1子串所有字符的目标串target,不在意字符顺序。
尺取法应用之一——滑动窗口
准备一个count数组记录str1子串中不同的字符的数量;
并定义一个total变量记录str1中字符总数,即str1的长度。
初始滑窗:从父串str2的0~str1.length-1范围内的窗口,此时滑窗会不断新增字符,即滑窗左边保持在0,右边从0开始移动到str1.length-1。
后续窗口:从父串的i~i+str1.length-1,i >=0,每次滑窗整体向右移动一格,即相较于上一个滑窗,会失去str2[i-1]字符,以及新增 str2[i+str1.length-1]字符。
滑窗其实相当于是一个str2的子串,我们可以基于滑窗来统计滑窗内子串各字符的数量,如果滑窗内各字符的数量与st1各字符数量一致,则说明滑窗内子串就是一个关联子串。
Python代码
'''
题目描述:关联子串:给定两个字符串str1和str2,如果字串str1中的字符经过排列组合后的字符串中,
只要有一个字符串是str2的子串,则认为str1是str2的关联子串。
'''
# 数据获取
str1, str2 = input().split(",")
#算法入口
def getResult():
# count用于统计str1中各种字符的数量
count = {}
for c in str1:
count[c] = count.get(c, 0) + 1
# total统计str1总共字符个数
total = len(str1)
# 初始滑窗,滑窗范围内容,就是一个子串
for i in range(total):
# 滑窗子串新增的字符
add = str2[i]
# 如果新增字符是str1的字符,即count[add] > 0时,则说明滑窗子串已找到一个目标字符,
# 此时剩余add字符数量count[add]--
if count.get(add) is not None:
if count[add] > 0:
total -= 1 # 匹配了一个字符
count[add] -= 1
# 如果total==0则说明滑窗所有字符都是str1的字符,由于限定滑窗的长度就是str1的长度,因此滑窗和str1完全匹配
if total == 0:
return 0
# 下一个滑窗范围是i~i+str1.length()-1
for i in range(1, len(str2) - len(str1) + 1):
# 相较于上一个滑窗失去的字符remove
remove = str2[i - 1]
# 相较于上一个滑窗新增的字符add
add = str2[i + len(str1) - 1]
# 本轮滑窗remove字符,在上一轮是add的字符,我们假设此字符为c
# 1.c是str1的字符,则初始统计时count[c]>0,上一轮滑窗加入c字符,则count[c]--,此轮count[c]是有可能>=0或<0,
# 1.1如果本轮count[c]>=0,则说明上轮滑窗并没有找到所有的c字符,因此本轮移除的c字符可以还原total的数量
# 1.2如果本轮count[c]<0,说明上一轮滑窗内的c字符超标了,即c字符是目标字符,但是滑窗内包含的c字符数量超过了str1中的
if count.get(remove) is not None:
if count[remove] >= 0:
total += 1
count[remove] += 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(getResult())

5507

被折叠的 条评论
为什么被折叠?



