先贴leetcode题目。
链接: link
题目叙述
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1
示例 1: 输入: haystack = "hello", needle = "ll" 输出: 2
示例 2: 输入: haystack = "aaaaa", needle = "bba" 输出: -1
解答
def getnext(s):
j = 0
next = [0]
for i in range(1, len(s)):
while j > 0 and s[i] != s[j]:
j = next[j - 1]
if s[i] == s[j]:
j += 1
next.append(j)
return next
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
result=[]
start=0
next=getnext(needle)
for i in range(len(haystack)):
if haystack[i]==needle[start]:
start+=1
if start>=len(needle):
return i-start+1
continue
else:
if start==0:
continue
while(start>0 and haystack[i]!=needle[start]):
start=next[start-1]
if haystack[i]==needle[start]:
start+=1
else:
start=0
return -1
暴力思路采用双循环这要容易超时,所以采用KMP算法。
如何使用?
首先先解释一下什么是前缀表。对应代码中的next数组。
如果输入字符串s
abbaab
对于这整个字符串来说,abbaa是前缀,bbaab是后缀。
next表就是依次遍历s,然后返回最大相同前后缀长度的值。
我们举例s说明:
遍历开始,相当于只有a
所以返回的是0
-
如表所示
- a ->0
- ab -0
- abba->1
- abbaa->1
- abbaab->0
到此就得到了next表。
[0,0,1,1,0]
接下来说明next的作用。
若需要查的是f
abbabvcc
如果需要搜寻的时候,当有字母不同的时候,s下标重新移向对应值进行重新判断。
我们模拟一下
当abba相等判断后,我们开始判断第5个字母不相等,所以需要回到s第4个所指向的,这样s回到了第1个字母a,显然这样就看到了这个所指向的和原来f的前一个是一样的都是a,这样就形成了循环。
可以自己debug一下。非常容易感觉出来。