题目:实现 strStr() 函数。给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例:
输入: haystack = "hello", needle = "ll"
输出: 2
输入: haystack = "aaaaa", needle = "bba"
输出: -1
思路:字符串匹配有一种比较经典和高效的算法:KMP,一般我们在做字符串匹配时是这么做的:
- 比较needle和haystack的第一个字符是否相同,若相同则比较第二个字符,以此类推。若中间某个字符不相同则跳到2,若所有字符均相同则返回第一个字符的位置。
- 将needle整体后移一个字符,重复执行步骤1
在介绍KMP之前,先介绍一个定义,字符串最长前缀:指的是使一个字符串的前k的字符与最后的k个字符相同的最大k值,比如“abcdabc”的最长前缀是3,因为前三个字符“abc”与后三个字符“abc”相同。
KMP算法的高效之处在于其改进了当前不匹配的情况下needle字符串整体后移的策略,具体来说步骤如下:
- 当前位置needle和haystack不匹配,但是二者前几个字符是相同的,令其为A,长度为M
- 寻找A的最长前缀,其长度为N
- needle整体向后移动M-N个长度,重新进行匹配
代码:
class Solution:
def get_max_substr(self,a_str):
max_lenth = 0
for i in range(1,len(a_str)):
if a_str[:i] == a_str[len(a_str)-i:] and i != len(a_str):
if i > max_lenth:
max_lenth = i
return a_str[:max_lenth]
def strStr(self, haystack, needle):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
i = 0
if not needle:
return 0
if not needle in haystack:
return -1
while i <= len(haystack)-len(needle):
matching = True
for j in range(len(needle)):
if haystack[i+j] == needle[j]:
continue
else:
matching = False
if j < 2:
i += 1
break
else:
matching_str = needle[:j]
max_substr = Solution.get_max_substr(self,matching_str)
i += (len(matching_str)-len(max_substr))
break
if matching:
return i