【LeetCode】28. 找出字符串中第一个匹配项的下标 【字符串单模匹配:KMP算法】
2023-12-13 04:27:13
Python3
直觉解法
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
pn, ph = 0, 0
n = len(needle)
h = len(haystack)
while ph < h:
if haystack[ph] == needle[pn]:
if pn == n-1: # 1234 123
return ph - len(needle) + 1
else:
pn += 1
ph += 1
else: ## 1234 122
ph = ph - pn + 1
pn = 0
return -1
方法一: 暴力解法 ? O ( n × m ) 、 O ( 1 ) ? \lgroup O(n\times m)、O(1) \rgroup ?O(n×m)、O(1)?
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
for i in range(0, len(haystack)-len(needle)+1):
if haystack[i:i+len(needle)] == needle:
return i
return -1
? 方法二:Knuth-Morris-Pratt 算法 [KMP算法] ? O ( m + n ) 、 O ( m ) ? \lgroup O(m+n)、O(m) \rgroup ?O(m+n)、O(m)? 【空间换时间】
从而实现 更快地 跳转
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
h = len(haystack)
n = len(needle)
# 获取 needle 的前缀信息
lis = [0] * n
j = 0 # 前后 子串长度
for i in range(1, n): # 需要前后比较, 1个字符无法比较,因此从 i=1 开始
while j > 0 and needle[i] != needle[j]:
j = lis[j-1] # 和之前 相等的长度一样
if needle[i] == needle[j]:
j += 1
lis[i] = j
# 0 1 2 3 4 5 6
# a a b a a a b needle
# 0 1 0 1 2 2 3 前缀子串 后缀子串 相同的长度 若是 needle[j] 不匹配了,注意是 lis[j-1] 存储的才是 待比较的下一个 j
# a a c a a
# 根据上述的 信息进行 匹配
j = 0 # 遍历 needle 下标
for i in range(0, h): # 遍历 haystack 下标
while j > 0 and haystack[i] != needle[j]: #
j = lis[j-1] # 这里 根据 前后缀 信息 快速跳转
if haystack[i] == needle[j]:
j += 1
if j == n: # needle 已全部匹配 因为前面的if 成立,j多加了1
return i - n + 1
return -1
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
def get_next():
for i in range(1, len(needle)):
k = fπ[i-1]
while needle[i] != needle[k]:
if k == 0:
k -= 1
break
else:
k = fπ[k-1]
fπ[i] = k+1
n = len(needle)
fπ = [0] * n
get_next() # 生成 needle 的next 数组
i = 0
j = 0
while i < len(haystack):
if haystack[i] == needle[j]:
i += 1
j += 1
elif j == 0:
i += 1
else:
j = fπ[j-1]
if j >= n:
return i - n
return -1
C++
KMP 算法 ? O ( h + n ) 、 O ( n ) ? \lgroup O(h+n)、O(n) \rgroup ?O(h+n)、O(n)?
class Solution {
public:
int strStr(string haystack, string needle) {
int h = haystack.size(), n = needle.size();
vector<int> lis(n);
for (int i = 1, j = 0; i < n; ++i){
while (j > 0 && needle[i] != needle[j]){
j = lis[j-1];
}
if (needle[i] == needle[j]){
++j;
}
lis[i] = j;
}
for (int i = 0, j = 0; i < h; ++i){
while (j > 0 && haystack[i] != needle[j]){
j = lis[j-1];
}
if (haystack[i] == needle[j]){
++j;
}
if (j == n){
return i - n + 1;
}
}
return -1;
}
};
暴力解法
class Solution {
public:
int strStr(string haystack, string needle) {
int h = haystack.size(), n = needle.size();
int j = 0, i = 0;
while (i < h){
if (haystack[i] == needle[j]){
if (j == n-1){
return i - n + 1;
}
else{
++j;
++i;
}
}
else{
j = 0;
i = i - j + 1;
}
}
return -1;
}
};
文章来源:https://blog.csdn.net/weixin_46034116/article/details/134610807
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!