找出字符串中第一个匹配项的下标
题干:
关键词:KMP
概念的理解,文字太繁琐了,看B站视频视频讲解
- 作用:字符串不匹配时,可以用之前比较过的信息避免从头进行匹配,降低时间复杂度
- next数组:记录模式串与文本串不匹配的时候,模式串应该从哪里开始重新匹配
思路
- next数组的构建
- 依据next数组,遍历文本串,看二者能否匹配上
实现
- next数组为-1的表达形式
- i,j分别为后缀和前缀末尾坐标
- 若s[i]与s[j]不匹配,j需要回退到next中记录的重新寻找公共部分的位置(暂时还是有些不太理解,还得钻研一下)
- 若匹配上了,更新next[i]的数据为j+1
- 文本串和模式串的匹配过程与next数组获取的代码结构类似,只是多了判断模式串是否遍历完的步骤
- 时间复杂度为O(m+n)
class Solution {
public:
void getnext(int*next,string& s){
int j=-1;
next[0]=j;
for(int i=1;i<s.size();i++){
while(j>=0&&s[i]!=s[j+1]){
j=next[j];
}
if(s[i]==s[j+1]){
j++;
}
next[i]=j;
}
}
int strStr(string haystack, string needle) {
if(needle.size()==0)
return 0;
int next[needle.size()];
getnext(next,needle);
int j=-1;
for(int i=0;i<haystack.size();i++){
while(j>=0&&haystack[i]!=needle[j+1]){
j=next[j];
}
if(haystack[i]==needle[j+1]){
j++;
}
if(j==needle.size()-1){
return(i-needle.size()+1);
}
}
return -1;
}
};
最开始写的时间复杂度为O(mn)的代码
class Solution {
public:
int strStr(string haystack, string needle) {
int m=haystack.size();
int n=needle.size();
for(int i=0;i<m;i++){
if(m-i<n){
return -1;
}
//开始进行第一个字母的比较
if(haystack[i]==needle[0]){
int j=i,k;
for(k=0;k<n;k++){
if(needle[k]!=haystack[j++])
break;
}
if(k==n)
return i;
}
}
return -1;
}
};