本文目录
- [1 中文题目](#1 中文题目)
- [2 求解方法:KMP算法](#2 求解方法:KMP算法)
-
- [2.1 方法思路](#2.1 方法思路)
- [2.2 Python代码](#2.2 Python代码)
- [2.3 复杂度分析](#2.3 复杂度分析)
- [3 题目总结](#3 题目总结)
1 中文题目
给定两个字符串 haystack
和 needle
,请在 haystack
字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle
不是 haystack
的一部分,则返回 -1 。
示例:
python
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。
python
输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。
提示:
- 1 ≤ h a y s t a c k . l e n g t h , n e e d l e . l e n g t h ≤ 1 0 4 1 \leq haystack.length, needle.length \leq 10^4 1≤haystack.length,needle.length≤104
haystack
和needle
仅由小写英文字符组成
2 求解方法:KMP算法
2.1 方法思路
方法核心
使用KMP算法实现字符串匹配,通过next数组(部分匹配表)优化匹配过程。并且避免不必要的回溯,提高效率
实现步骤
(1)构建next数组:
- 计算模式串的最长相同前后缀
- 用于在不匹配时快速回退
(2)字符串匹配:
- 遍历主串进行匹配
- 利用next数组进行高效回退
- 找到完全匹配时返回起始位置
方法示例
python
输入:haystack = "hello", needle = "ll"
1. 构建next数组:
needle = "ll"
next = [0, 1]
2. 匹配过程:
"hello"
j=0
i=0 h!=l j=0
i=1 e!=l j=0
i=2 l=l j=1
i=3 l=l j=2 (匹配成功)
返回值:2
2.2 Python代码
python
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
# 如果needle为空,返回0
if not needle:
return 0
# 获取两个字符串的长度
n, m = len(haystack), len(needle)
# 构建next数组(部分匹配表)
def get_next(pattern):
# next[i]表示pattern[0:i]的最长相同前后缀长度
next = [0] * m
# j指向前缀末尾,i指向后缀末尾
j = 0
# 从第二个字符开始计算next数组
for i in range(1, m):
# 当前字符不匹配,需要回退
while j > 0 and pattern[i] != pattern[j]:
j = next[j - 1]
# 当前字符匹配,更新j
if pattern[i] == pattern[j]:
j += 1
# 记录当前位置的最长相同前后缀长度
next[i] = j
return next
# 获取next数组
next = get_next(needle)
# j指向needle的匹配位置
j = 0
# 遍历haystack进行匹配
for i in range(n):
# 当前字符不匹配,根据next数组回退
while j > 0 and haystack[i] != needle[j]:
j = next[j - 1]
# 当前字符匹配,移动j
if haystack[i] == needle[j]:
j += 1
# 完全匹配,返回起始位置
if j == m:
return i - m + 1
# 未找到匹配,返回-1
return -1
2.3 复杂度分析
- 时间复杂度:O(n + m),n是haystack长度,m是needle长度
- 构建next数组需要O(m)
- 匹配过程需要O(n)
- 空间复杂度:O(m)
- next数组占用O(m)空间
- 其他变量占用O(1)空间
3 题目总结
题目难度:简单
数据结构:字符串
应用算法:KMP算法