28. 找出字符串中第一个匹配项的下标
28. 找出字符串中第一个匹配项的下标
薛谔一、暴力解法
- 思路:
- 遍历主字符串
haystack
,对于每个字符,尝试从该位置开始与模式字符串needle
进行逐字符匹配。 - 若在某一位置能完整匹配上
needle
,则返回该位置作为第一个匹配项的下标;若遍历完整个haystack
都未找到完整匹配,则返回 -1。
- 遍历主字符串
- 示例代码片段:
1 | def strStr(haystack, needle): |
- 时间复杂度:在最坏情况下,对于主字符串
haystack
的每个字符都要尝试进行长度为len(needle)
的匹配,所以时间复杂度为 ,其中 是haystack
的长度, 是needle
的长度。 - 空间复杂度:只用到了常数级别的额外空间,所以空间复杂度为 。
二、KMP 算法(Knuth-Morris-Pratt 算法)
- 思路:
- KMP 算法主要利用了已经匹配过的部分信息来避免不必要的重新匹配。
- 首先通过预处理模式字符串
needle
,构建一个next
数组(也叫部分匹配表),它记录了模式字符串自身在不同位置上的最长公共前后缀长度。 - 在匹配过程中,当主字符串
haystack
和模式字符串needle
在某一位置不匹配时,利用next
数组快速将模式字符串的指针移动到合适位置继续匹配,而不是像暴力解法那样每次都从头开始重新匹配模式字符串。
- 示例代码片段(以 Python 为例):
1 | def strStr(haystack, needle): |
- 时间复杂度:预处理
next
数组的时间复杂度为 ,其中 是模式字符串needle
的长度。在匹配过程中,指针最多移动 次( 是主字符串haystack
的长度),所以整体时间复杂度为 。 - 空间复杂度:除了存储主字符串和模式字符串本身的空间外,需要一个长度为
n
的next
数组来辅助计算,所以空间复杂度为 。
三、其他优化思路及变体
- 有些解法可能会基于编程语言的内置函数进行巧妙实现。比如在 Python 中,可以利用字符串的
find
方法直接求解,但这在实际面试等场景中可能不符合考察通过算法实现的本意。 - 还有一些可能是对 KMP 算法的进一步优化或采用类似思路但实现细节略有不同的算法,比如改进
next
数组的计算方式以提高效率等。
总体而言,本题主要考察对字符串匹配算法的掌握,从简单直接的暴力解法到更高效的 KMP 算法及其变种等,不同解法在时间和空间复杂度上各有优劣。