基础数据结构篇(下)LeetCode 字符串与字符串匹配

74 阅读3分钟

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

image.png

2156. 查找给定哈希值的子串

解题思路

滑动窗口,数学计算。首先根据题意,计算长度为 k 的字符串 s 的子串哈希值,然后在滑动窗口过程中,推算新的子串的哈希值,保存哈希值等于 hashValue 的子串起始下标,最后返回结果 s[pos: pos + k]
递推公式为哈希值 h

h=((hval(s[i+k])mult  %  modulo+modulo)power+val(s[i]))  %  moduloh = ((h - val(s[i+k]) * mult \;\%\; modulo + modulo) * power + val(s[i])) \;\%\; modulo

其中 mult=powerk1  %  module mult = power ^{k - 1} \;\%\; module

代码

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]

image.png

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)

image.png

1023. 驼峰式匹配

解题思路

动态规划。
主要解决 2 个字符串匹配问题,即函数 check(s, pattern)
对于字符串 spattern,字符串长度分别为 mn,初始下标 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

image.png

参考资料

LeetCode 算法笔记 (datawhalechina.github.io)