代码随想录算法训练营第九天 |28. 找出字符串中第一个匹配项的下标(实现strStr())、 KMP算法

78 阅读1分钟

28. 找出字符串中第一个匹配项的下标(实现strStr())

代码随想录视频讲解_理论篇

代码随想录视频讲解_代码篇

代码随想录文章讲解

使用库函数

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        return haystack.find(needle)

暴力解法

  • 如果needle在haystack存在,起始点一定不会大于len(haystack) - len(needle) + 1
# Time complexity: O((M-N)*N)
# Space complexity: O(1)
class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        for i in range(len(haystack) - len(needle) + 1):
            if haystack[i] == needle[0]:
                flag = True
                for j in range(1, len(needle)):
                    if needle[j] != haystack[i+j]:
                        flag = False
                        break
                if flag:
                    return i
        return -1

KMP算法

  • 构建最长公共前缀后缀list(LPS):

    prevLPS同时是字符i的最长公共前缀后缀的数值

    • 如果字符相等,prevLPS +=1lps[i] = prevLPS
    • 如果不等,prevLPS回退到 lps[prevLPS-1]的位置再进行比较,一直到字符相等或prevLPS = 0
    • 更新lps[i]=prevLPS,并向前移动i指针
  • 比较haystack和needle,当字符不相等时,利用最长公共前缀后缀list来找到下一个需要比较的字符下标(更新j = lps[j-1]

# Time complexity: O(M+N)
# Space complexity: O(N)
class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        if needle == "":
            return 0
        # stands for longest preffix suffix, length always equals to len(needle)
        lps = [0] * len(needle)
        prevLPS = 0
        for i in range(1, len(needle)):
            while prevLPS > 0 and needle[i] != needle[prevLPS]:
                prevLPS = lps[prevLPS-1]
            if needle[i] == needle[prevLPS]:
                prevLPS += 1
            lps[i] = prevLPS
​
        i, j = 0, 0
        while i < len(haystack):
            if haystack[i] == needle[j]:
                i, j = i+1, j+1
            else:
                if j != 0:
                    j = lps[j-1]
                else:
                    i += 1
            if j == len(needle):
                return i - len(needle)
​
        return -1