LeetCode 28. 实现 strStr()
题目:
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例 1:
输入: haystack = "hello", needle = "ll"
输出: 2
示例 2:
输入: haystack = "aaaaa", needle = "bba"
输出: -1
说明:
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
思路:
从stack那边找到匹配的第一个字符为止,找到继续,找不到跳过继续匹配,当余下长度小于needle 长度则认为找不到返回-1.
方法一:
忍不住想用find..呵呵呵.
class Solution(object):
def strStr(self, haystack, needle):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
len_s = len(haystack)
len_n = len(needle)
if len_n == 0:
return 0
return haystack.find(needle)
方法二:
依次查找,以needle的长度去遍历,找到就返回位置,找不到返回-1,因为是遍历所有长度,所以可以加一个检查,当stack的i位置不等于needle的首字符就跳过,减少时间。
class Solution(object):
def strStr(self, haystack, needle):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
len_s = len(haystack)
len_n = len(needle)
if len_n == 0:
return 0
for i in xrange(len_s-len_n+1):
if haystack[i] != needle[0]:
continue
while (haystack[i:i+len_n] == needle):
return i
return -1
或者是双指针移动归位计算,匹配到就返回,匹配不到就依次进一位。
class Solution(object):
def strStr(self, haystack, needle):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
len_s, len_n = len(haystack), len(needle)
if L == 0:
return 0
start = 0
while start < len_s - len_n + 1:
curr_len = 0
while curr_len < len_n and haystack[start] == needle[curr_len]:
start += 1
curr_len += 1
if curr_len == len_n:
return start - len_n
start = start - curr_len + 1
return -1
方法三:
KMP算法,研究了好几个博客,终于圆上为什么可以直接移动k....这个解释了。
不过我是说不出来,大概就是知道它为什么要这样写。
记录下KMP算法大佬们的心得。
下面转自提解大大yi-wen-statistics 本题的KMP 算法解释。
方法二中可能存在不少的重复性对比,例如'ABCDFABCDE'与'ABCDE'进行匹配,依照BF算法,需要按顺序逐个比较但实际上第一轮对比过程中发现'E'与'F'不同时可以直接将待匹配字符串向后挪移四格,这样就大大缩短了匹配时间,而KMP的核心思想便在于此——永不回溯。
但还存在一个问题,如果待匹配字符串中出现相同的模式,例如'BBCBBB',且恰好字符库中也存在这样的模式(也可以认为是部分匹配),这时就无法按照上面的方式进行移动了,因此我们还需要一个跳跃数组来辅助我们的对比,我们每次遇到不相同的字符后,就将指针跳跃到后缀字符中部分匹配的位置,这样一来就能避免漏判的情况。
class Solution(object):
def strStr(self, haystack, needle):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
n = len(needle)
m = len(haystack)
if n == 0: return 0
j = 0
pnext = self.getnext(needle)
for i in range(m):
while j > 0 and needle[j] != haystack[i]:
j = pnext[j]
if needle[j] == haystack[i]:
j += 1
if j == n:
return i-n+1
return -1
def getnext(self, s):
n = len(s)
pnext = [0, 0] # 多一个前导0是为了方便后续指针跳跃,避免死循环
j = 0
for i in range(1, n):
while j > 0 and s[i] != s[j]:
j = pnext[j] # 指针跳跃
if s[j] == s[i]:
j += 1
pnext.append(j)
return pnext