update 0028.实现strStr:改错字,优化python代码格式

This commit is contained in:
Yuhao Ju
2022-11-26 20:48:23 +08:00
committed by GitHub
parent 99f0f22862
commit f95a4b6ab4

View File

@ -94,7 +94,7 @@ next数组就是一个前缀表prefix table
**前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。** **前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。**
为了清楚了解前缀表的来历,我们来举一个例子: 为了清楚了解前缀表的来历,我们来举一个例子:
要在文本串aabaabaafa 中查找是否出现过一个模式串aabaaf。 要在文本串aabaabaafa 中查找是否出现过一个模式串aabaaf。
@ -110,9 +110,9 @@ next数组就是一个前缀表prefix table
![KMP详解1](https://code-thinking.cdn.bcebos.com/gifs/KMP%E7%B2%BE%E8%AE%B21.gif) ![KMP详解1](https://code-thinking.cdn.bcebos.com/gifs/KMP%E7%B2%BE%E8%AE%B21.gif)
动画里,我特意把 子串`aa` 标记上了,这是有原因的,大家先注意一下,后面还会说 动画里,我特意把 子串`aa` 标记上了,这是有原因的,大家先注意一下,后面还会说
可以看出文本串中第六个字符b 和 模式串的第六个字符f不匹配了。如果暴力匹配发现不匹配,此时就要从头匹配了。 可以看出文本串中第六个字符b 和 模式串的第六个字符f不匹配了。如果暴力匹配发现不匹配此时就要从头匹配了。
但如果使用前缀表就不会从头匹配而是从上次已经匹配的内容开始匹配找到了模式串中第三个字符b继续开始匹配。 但如果使用前缀表就不会从头匹配而是从上次已经匹配的内容开始匹配找到了模式串中第三个字符b继续开始匹配。
@ -157,7 +157,7 @@ next数组就是一个前缀表prefix table
以下这句话,对于理解为什么使用前缀表可以告诉我们匹配失败之后跳到哪里重新匹配 非常重要! 以下这句话,对于理解为什么使用前缀表可以告诉我们匹配失败之后跳到哪里重新匹配 非常重要!
**下标5之前这部分的字符串也就是字符串aabaa的最长相等的前缀 和 后缀字符串是 子字符串aa ,因为找到了最长相等的前缀和后缀,匹配失败的位置是后缀子串的后面,那么我们找到与其相同的前缀的后面新匹配就可以了。** **下标5之前这部分的字符串也就是字符串aabaa的最长相等的前缀 和 后缀字符串是 子字符串aa ,因为找到了最长相等的前缀和后缀,匹配失败的位置是后缀子串的后面,那么我们找到与其相同的前缀的后面新匹配就可以了。**
所以前缀表具有告诉我们当前位置匹配失败,跳到之前已经匹配过的地方的能力。 所以前缀表具有告诉我们当前位置匹配失败,跳到之前已经匹配过的地方的能力。
@ -199,7 +199,7 @@ next数组就是一个前缀表prefix table
所以要看前一位的 前缀表的数值。 所以要看前一位的 前缀表的数值。
前一个字符的前缀表的数值是2把下标移动到下标2的位置继续比配。 可以再反复看一下上面的动画。 前一个字符的前缀表的数值是2把下标移动到下标2的位置继续比配。 可以再反复看一下上面的动画。
最后就在文本串中找到了和模式串匹配的子串了。 最后就在文本串中找到了和模式串匹配的子串了。
@ -211,7 +211,7 @@ next数组就可以是前缀表但是很多实现都是把前缀表统一减
为什么这么做呢,其实也是很多文章视频没有解释清楚的地方。 为什么这么做呢,其实也是很多文章视频没有解释清楚的地方。
其实**这并不涉及到KMP的原理而是具体实现next数组可以就是前缀表,也可以是前缀表统一减一(右移一位,初始位置为-1。** 其实**这并不涉及到KMP的原理而是具体实现next数组可以就是前缀表,也可以是前缀表统一减一(右移一位,初始位置为-1。**
后面我会提供两种不同的实现代码,大家就明白了。 后面我会提供两种不同的实现代码,大家就明白了。
@ -231,7 +231,7 @@ next数组就可以是前缀表但是很多实现都是把前缀表统一减
其中n为文本串长度m为模式串长度因为在匹配的过程中根据前缀表不断调整匹配的位置可以看出匹配的过程是O(n)之前还要单独生成next数组时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)的。 其中n为文本串长度m为模式串长度因为在匹配的过程中根据前缀表不断调整匹配的位置可以看出匹配的过程是O(n)之前还要单独生成next数组时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)的。
暴力的解法显而易见是O(n × m),所以**KMP在字符串匹配中极大提高搜索的效率。** 暴力的解法显而易见是O(n × m),所以**KMP在字符串匹配中极大提高搜索的效率。**
为了和力扣题目28.实现strStr保持一致方便大家理解以下文章统称haystack为文本串, needle为模式串。 为了和力扣题目28.实现strStr保持一致方便大家理解以下文章统称haystack为文本串, needle为模式串。
@ -251,7 +251,7 @@ void getNext(int* next, const string& s)
2. 处理前后缀不相同的情况 2. 处理前后缀不相同的情况
3. 处理前后缀相同的情况 3. 处理前后缀相同的情况
接下来我们详解详解一下。 接下来我们详解一下。
1. 初始化: 1. 初始化:
@ -613,12 +613,12 @@ class Solution {
public void getNext(int[] next, String s){ public void getNext(int[] next, String s){
int j = -1; int j = -1;
next[0] = j; next[0] = j;
for (int i = 1; i<s.length(); i++){ for (int i = 1; i < s.length(); i++){
while(j>=0 && s.charAt(i) != s.charAt(j+1)){ while(j >= 0 && s.charAt(i) != s.charAt(j+1)){
j=next[j]; j=next[j];
} }
if(s.charAt(i)==s.charAt(j+1)){ if(s.charAt(i) == s.charAt(j+1)){
j++; j++;
} }
next[i] = j; next[i] = j;
@ -632,14 +632,14 @@ class Solution {
int[] next = new int[needle.length()]; int[] next = new int[needle.length()];
getNext(next, needle); getNext(next, needle);
int j = -1; int j = -1;
for(int i = 0; i<haystack.length();i++){ for(int i = 0; i < haystack.length(); i++){
while(j>=0 && haystack.charAt(i) != needle.charAt(j+1)){ while(j>=0 && haystack.charAt(i) != needle.charAt(j+1)){
j = next[j]; j = next[j];
} }
if(haystack.charAt(i)==needle.charAt(j+1)){ if(haystack.charAt(i) == needle.charAt(j+1)){
j++; j++;
} }
if(j==needle.length()-1){ if(j == needle.length()-1){
return (i-needle.length()+1); return (i-needle.length()+1);
} }
} }
@ -694,9 +694,9 @@ class Solution(object):
:type needle: str :type needle: str
:rtype: int :rtype: int
""" """
m,n=len(haystack),len(needle) m, n = len(haystack), len(needle)
for i in range(m): for i in range(m):
if haystack[i:i+n]==needle: if haystack[i:i+n] == needle:
return i return i
return -1 return -1
``` ```
@ -704,31 +704,31 @@ class Solution(object):
// 方法一 // 方法一
class Solution: class Solution:
def strStr(self, haystack: str, needle: str) -> int: def strStr(self, haystack: str, needle: str) -> int:
a=len(needle) a = len(needle)
b=len(haystack) b = len(haystack)
if a==0: if a == 0:
return 0 return 0
next=self.getnext(a,needle) next = self.getnext(a,needle)
p=-1 p=-1
for j in range(b): for j in range(b):
while p>=0 and needle[p+1]!=haystack[j]: while p >= 0 and needle[p+1] != haystack[j]:
p=next[p] p = next[p]
if needle[p+1]==haystack[j]: if needle[p+1] == haystack[j]:
p+=1 p += 1
if p==a-1: if p == a-1:
return j-a+1 return j-a+1
return -1 return -1
def getnext(self,a,needle): def getnext(self,a,needle):
next=['' for i in range(a)] next = ['' for i in range(a)]
k=-1 k = -1
next[0]=k next[0] = k
for i in range(1,len(needle)): for i in range(1, len(needle)):
while (k>-1 and needle[k+1]!=needle[i]): while (k > -1 and needle[k+1] != needle[i]):
k=next[k] k = next[k]
if needle[k+1]==needle[i]: if needle[k+1] == needle[i]:
k+=1 k += 1
next[i]=k next[i] = k
return next return next
``` ```
@ -736,34 +736,34 @@ class Solution:
// 方法二 // 方法二
class Solution: class Solution:
def strStr(self, haystack: str, needle: str) -> int: def strStr(self, haystack: str, needle: str) -> int:
a=len(needle) a = len(needle)
b=len(haystack) b = len(haystack)
if a==0: if a == 0:
return 0 return 0
i=j=0 i = j = 0
next=self.getnext(a,needle) next = self.getnext(a, needle)
while(i<b and j<a): while(i < b and j < a):
if j==-1 or needle[j]==haystack[i]: if j == -1 or needle[j] == haystack[i]:
i+=1 i += 1
j+=1 j += 1
else: else:
j=next[j] j = next[j]
if j==a: if j == a:
return i-j return i-j
else: else:
return -1 return -1
def getnext(self,a,needle): def getnext(self, a, needle):
next=['' for i in range(a)] next = ['' for i in range(a)]
j,k=0,-1 j, k = 0, -1
next[0]=k next[0] = k
while(j<a-1): while(j < a-1):
if k==-1 or needle[k]==needle[j]: if k == -1 or needle[k] == needle[j]:
k+=1 k += 1
j+=1 j += 1
next[j]=k next[j] = k
else: else:
k=next[k] k = next[k]
return next return next
``` ```