✅DAY9 字符串+KMP | 151.翻转字符串里的单词 | 卡码网:55.右旋转字符串 | 28. 实现 strStr() | 459.重复的子字符串 | 字符串总结 | 双指针回顾

小伙伴们共勉~

***KPM算法***

核心思想是:当某个字符不匹配时,不需要重新从头开始匹配,而是利用已经部分匹配的结果,通过一个 部分匹配表(next 数组) 来跳过那些已经比较过的字符,从而减少不必要的重复计算。

151.翻转字符串里的单词

解题思路:step1: strip() 把左右多余空格删除 step2: 反转整个字符串 step3: 把每个空格前的单词转回去

class Solution:
    def reverseWords(self, s: str) -> str:
        s = s.strip()
        s = s[::-1]
        s = ''.join(word[::-1] for word in s.split())
        return s

解题思路:把string变成单词,交换左右位置

# 使用 ' ' 作为分隔符将单词列表拼接成字符串

class Solution:
    def reverseWords(self, s: str) -> str:
        s = s.strip()
        words = s.split()

        left, right = 0, len(words)-1
        while left < right:
            words[left], words[right] = words[right], words[left]
            left += 1
            right -=1
        return ' '.join(words)

解题思路:直接把string变成list words,反转所有位置。

最后用[::-1] 和 reversed() 都可以

时间复杂度:O(n),其中 n 是字符串 s 的长度。split() 和 join() 都是 O(n) 的操作。

空间复杂度:O(n),用于存储分割后的单词列表和反转后的字符串。

class Solution:
    def reverseWords(self, s: str) -> str:
        words = s.split()
        #words = words[::-1]
        #return ' '.join(words)

        return ' '.join(reversed(words))

卡码网:55.右旋转字符串

解题思路:对于python可能有点作弊?

k = int(input())
s = input()

print( s[-k:] + s[:-k] )

28. 实现 strStr()

解题思路:直接比较切片内容是否一致

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        if needle == '':
            return 0
        for i in range(len(haystack)+1-len(needle)):
            #只留足够needle空位的长度
            if haystack[i:i+len(needle)] == needle:
                return i

        return -1
            

解题思路:KMP算法解法(看了又看还是一知半解)

class Solution:
    def getNext(self, next: List[int], s: str) -> None:
        # 构建 next 数组,用于存储模式串的部分匹配信息
        j = 0  # j 用来表示前缀的长度
        next[0] = 0  # 第一个字符的 next 值为 0
        for i in range(1, len(s)):  # 从第二个字符开始计算 next 数组
            while j > 0 and s[i] != s[j]:
                j = next[j - 1]  # 回退到前一个最长前缀的位置
            if s[i] == s[j]:  # 如果字符匹配,前缀长度增加
                j += 1
            next[i] = j  # 记录当前字符的 next 值

    def strStr(self, haystack: str, needle: str) -> int:
        # 特殊情况:如果 needle 为空,返回 0
        if len(needle) == 0:
            return 0

        # 生成模式串 needle 的 next 数组
        next = [0] * len(needle)
        self.getNext(next, needle)

        j = 0  # 模式串的指针
        for i in range(len(haystack)):  # 遍历主串 haystack
            while j > 0 and haystack[i] != needle[j]:
                j = next[j - 1]  # 不匹配时,跳到 next[j-1]
            if haystack[i] == needle[j]:
                j += 1  # 如果匹配,模式串指针 j 向右移动
            if j == len(needle):  # 完全匹配时返回匹配的起始位置
                return i - len(needle) + 1
        
        return -1  # 没有匹配到,返回 -1

459.重复的子字符串

解题思路:构造字符串

1. s + s:将字符串 s 复制两份。例如,如果 s = "abcabc",那么 s + s = "abcabcabcabc"。

2. [1:-1]:去掉 s + s 的第一个和最后一个字符。例如,s + s = "abcabcabcabc" 变成 "bcabcabcab"。

3. find(s):检查去掉首尾字符的字符串中是否还能找到原字符串 s。如果能找到,说明 s 是由某个子串重复构成的,返回 True;否则返回 False。

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        # 将字符串 s 复制两份,去掉头尾,判断 s 是否在中间
        return (s + s)[1:-1].find(s) != -1

解题思路:KMP解法***

输入: "abab"
next 数组: [0, 0, 1, 2]  # 表示前缀 "ab" 是一个长度为 2 的重复子串
解释: 字符串长度 4,前缀长度 2,可以被整除,返回 True

输入: "aba"
next 数组: [0, 0, 1]  # 无法被子串重复多次构成
解释: 返回 False

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        if len(s) == 0:
            return False  # 边界条件:空字符串直接返回 False
        
        # 构建 next 数组,用于存储前缀的匹配情况
        next = [0] * len(s)
        self.getNext(next, s)
        
        # 判断条件:
        # 1. next[-1] != 0:表示存在相同前后缀
        # 2. len(s) % (len(s) - next[-1]) == 0:表示字符串的长度能被重复子串的长度整除
        if next[-1] != 0 and len(s) % (len(s) - next[-1]) == 0:
            return True
        return False
        
    # 计算 next 数组
    def getNext(self, next, s: str):
        next[0] = 0  # 初始化,第一个字符的前缀长度为 0
        j = 0  # j 用来表示前缀的长度

        # 从第二个字符开始,逐步构建 next 数组
        for i in range(1, len(s)):
            # 当不匹配时,通过 next 数组回溯,找到可以继续匹配的前缀
            while j > 0 and s[i] != s[j]:
                j = next[j - 1]  # 回到上一个最长前缀的长度
            
            # 如果匹配上了,前缀长度 j + 1
            if s[i] == s[j]:
                j += 1
            next[i] = j  # 将当前匹配的前缀长度记录在 next 数组中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值