(1)问题
力扣——28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle
不是 haystack
的一部分,则返回 -1
。
示例 1:
输入:haystack = "sadbutsad", needle = "sad" 输出:0 解释:"sad" 在下标 0 和 6 处匹配。 第一个匹配项的下标是 0 ,所以返回 0 。
示例 2:
输入:haystack = "leetcode", needle = "leeto" 输出:-1 解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。
(2)思路
第一种:使用两个for循环进行匹配。时间复杂度O(n^2)。
第二种:使用KMP算法进行匹配。(本文使用这种方法)。
(3)KMP算法
KMP算法是一种用于字符串匹配的高效算法。其核心思想是——利用已匹配的部分信息,通过一个部分匹配表(next数组),从而避免不必要的回溯。KMP算法的时间复杂度为O(n+m)。
KMP算法的实现核心就是构造这个部分匹配表。其中涉及到找最大前后缀与存储。原理可以看代码随想录。
(4)解题思路
1.将一些特殊情况排除,例如字符串为0的情况。
2.创建一个容器用来当做next数组。
3.创建next数组。
4.遍历文本字符串,如果存在文本字符串与匹配字符串不相等的就回溯。
5.如果相等,匹配字符串下标+1;
6.如果匹配字符串到达最后,说明匹配成功,用文本字符串下标减去匹配字符串长度再加1。
void getNext(int* next,const string& s)
{
//j前缀起点,i后缀起点
int j=0;
next[0] = 0;
for(int i=1;i<s.size();i++)
{
while(j>0&&s[i]!=s[j])
{
j=next[j-1];
}
if(s[i]==s[j]) j++;
next[i] = j;
}
}
int strStr(string haystack, string needle) {
if(haystack.size()==0||needle.size()==0) return -1;
vector<int> next(needle.size());
getNext(&next[0],needle);
for(int i=0,j=0;i<haystack.size();i++)
{
while(j>0&&haystack[i]!=needle[j]) j=next[j-1];
if(haystack[i]==needle[j])
{
j++;
}
if(j==needle.size()) return i-j+1;
}
return -1;
}