28. 找出字符串中第一个匹配项的下标 python

本题太痛了,想了四天,给KMP跪了

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1 

class Solution:
    # # KMP
    # def getNext(self, s):
    #     nextt = [0] * len(s)
    #     j = 0
    #     for i in range(1, len(s)):
    #         if s[i] == s[j]:
    #             j += 1
    #             nextt[i] = j
    #         while j > 0 and s[i] != s[j]:
    #             j = nextt[j - 1]
    #     return nextt
    # 以上为错误版本
    # 以下为正确版本
    # 差就差在for循环内if和while的先后顺序
    # KMP
    def getNext(self, s):
        nextt = [0] * len(s)
        j = 0
        for i in range(1, len(s)):
            while j > 0 and s[i] != s[j]:
                    j = nextt[j - 1]
            if s[i] == s[j]:
                j += 1
                nextt[i] = j
    # 必须先判断不等再判断相等。先while再if。否则 若needle是'abab',本来next应该是[0012],错误版本得到的是[0010]
    # 原因在于判断s[i] == s[j]时,判断到j0(a) i2(a)相等,下一步是j自增变j1(b),然后next[2]=1
    # 然后本应i自增变i3(b)然后进入j1(b)和i3(b)相等的if判断,但错误版本直接进入j1(b)和i2(a)不等的while判断了。
        return nextt
        
    def strStr(self, haystack: str, needle: str) -> int:
        nextt = self.getNext(needle)
        i = 0
        j = 0
        if len(haystack) < len(needle):
            return -1

        while i < len(haystack):
            
            while j > 0 and haystack[i] != needle[j]:
            # while j > 0 and needle[j]: # 这他妈反而能通过55/79 为何
                j = nextt[j - 1]
            # 字母不同的时候就往回退 此时i不动,j一直退,直到j退到0跳出循环,或者遇到字母相同的情况

            if haystack[i] == needle[j]:
                i += 1
                j += 1
            # 字母相同的时候就往前走 此时i和j同步往前走
            
            if j == len(nextt):
                return i -len(nextt)
            # 当j走完时说明得到这样的字符串了,返回i在第一个匹配项的下标
            
            if j == 0 and i < len(haystack):
                i += 1
            # 当j回退到0时说明本次匹配尝试失败,i自增直到遇到下一个匹配项或字符串结束
            
            # 匹配成功时j才自增,匹配失败时j回退,未找到第一个匹配项时j一直在0索引处
        return -1

你可能感兴趣的:(python,开发语言)