03.02 字符串与字符串匹配
3. 无重复字符的最长子串
解题思路
滑动窗口。
使用 seen = set() 保存已观察到的字符,left 变量代表滑动窗口的左侧下标。
curlen 表示当前滑动窗口的长度,ans 表示最长子串的长度。
遍历字符串 s,如果字符 x 已在 seen 中出现,则增加滑动窗口左侧下标 left,同时 curlen 减 1,直到未出现重复字符。更新 ans,将 x 保存到 seen 中。遍历结束,返回结果 ans。
代码
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
left = 0
seen = set()
n = len(s)
ans = 0
curlen = 0
for x in s:
curlen += 1
while x in seen:
seen.remove(s[left])
left += 1
curlen -= 1
ans = max(ans, curlen)
seen.add(x)
return ans
2156. 查找给定哈希值的子串
解题思路
滑动窗口,数学计算。首先根据题意,计算长度为 k 的字符串 s 的子串哈希值,然后在滑动窗口过程中,推算新的子串的哈希值,保存哈希值等于 hashValue 的子串起始下标,最后返回结果 s[pos: pos + k]。
递推公式为哈希值 h
其中
代码
class Solution:
def subStrHash(self, s: str, power: int, modulo: int, k: int, hashValue: int) -> str:
mult = 1
n = len(s)
pos = -1
h = 0
for i in range(n - 1, n - k - 1, -1):
h = (h * power + (ord(s[i]) - ord('a') + 1)) % modulo
if i != n - k:
mult = mult * power % modulo
if h == hashValue:
pos = n - k
for i in range(n - k - 1, -1, -1):
h = ((h - (ord(s[i + k]) - ord('a') + 1) * mult % modulo + modulo) * power +
(ord(s[i]) - ord('a') + 1)) % modulo
if h == hashValue:
pos = i
return s[pos: pos + k]
676. 实现一个魔法字典
解题思路
将字符串 searWord 中一个字母换成另一个字母,不改变字符串长度。因此可以将 dictionary 中的字符串按照字符串长度进行归类。我的代码中使用 defaultdict(list) 来进行存储。
接着对于字符串 searchWord ,只需要在 dictionary 中检查与之长度相同的字符串即可。
采用逐个字符比较的方式,使用 cnt 表示两个字符串不相同的字母个数。遇到不同字母 cnt 加一,如果比较结束 cnt == 1,则匹配成功。
代码
class MagicDictionary:
def __init__(self):
self.d = defaultdict(list)
def buildDict(self, dictionary: List[str]) -> None:
for s in dictionary:
self.d[len(s)].append(s)
def search(self, searchWord: str) -> bool:
n = len(searchWord)
if n not in self.d:
return False
for s in self.d[n]:
cnt = 0
for c1, c2 in zip(searchWord, s):
if c1 != c2:
cnt += 1
if cnt > 1:
break
if cnt == 1:
return True
return False
# Your MagicDictionary object will be instantiated and called as such:
# obj = MagicDictionary()
# obj.buildDict(dictionary)
# param_2 = obj.search(searchWord)
1023. 驼峰式匹配
解题思路
动态规划。
主要解决 2 个字符串匹配问题,即函数 check(s, pattern)。
对于字符串 s 和 pattern,字符串长度分别为 m, n,初始下标 i = 0, j = 0。
遍历两个字符串
- 如果字母相同
s[i] == pattern[j],则继续遍历。 - 否则不相同,如果
s[i]不是小写字母,则匹配失败。 - 如果 j < n,则匹配失败。
- 接下来,如果
s[i:m]中出现非小写字母,则匹配失败。
代码
class Solution:
def camelMatch(self, queries: List[str], pattern: str) -> List[bool]:
def check(s, pattern):
m, n = len(s), len(pattern)
i, j = 0, 0
while i < m and j < n:
if s[i] == pattern[j]:
j += 1
i += 1
elif i < m:
if not s[i].islower():
break
else:
i += 1
if j < n:
return False
while i < m:
if not s[i].islower():
return False
i += 1
return True
ans = [check(s, pattern) for s in queries]
return ans