一、题目描述
二、思路
使用KMP算法去解决,关于KMP算法以及前缀表的具体内容:帮你把KMP算法学个通透!
关于计算 needle 字符串的前缀表(数值什么的与动图稍有不同,但思路相同):
- 首先令 j = 0,i = 1,且next [ 0 ] = 0;
- 开始进入循环比较 needle [ j ] 与 needle [ i ] :
- 若二者不同,令 j 倒退成 next [ j - 1 ],即 j = next [ j - 1 ],并再次比较,直至找到相同的字符或者 j > 0 为止;(为啥是倒退回next [ j - 1 ] 嘞?因为当 s[ j ] 的前一个元素的 next 数组的值不为零时,则前边有与它相等的前缀,那么倒退回 j = next [ j - 1 ] ,即指向上一组最长相等前后缀中前缀的后一个元素去判断是否与此时的 s [ i ] 相等)
- 若二者相同时,j++;
- 最后将 j 赋值给 next [ i ] 后继续循环;
关于比较 haystack 与 needle,判断 haystack 字符串中是否包含 needle 字符串(数值什么的与动图稍有不同,但思路相同):
- 初始化 i = 0, j = 0;
- 先判断 needle 是否为空字符串,是则直接输出 0;(不知道为啥,但是说是说这与C语言的 strstr() 以及 Java的 indexOf() 定义相符)
- 开始比较 haystack[ i ] 和 needle[ j ]:
- 当 haystack[ i ] != needle[ j ] 并且 j > 0 时,将 j 跳到 next [ j - 1 ],即 j = next [ j - 1 ];(为啥跳到 next [ j - 1 ] 嘞?因为若next [ j - 1 ] != 0 时,则代表此时的 haystack [ i ] 前 next [ j - 1 ] 个元素与 needle 字符串前 next [ j - 1 ] 相同,直接去比较后面的就成)
- 当 haystack[ i ] == needle[ j ],继续循环直至 i 等于 haystack 的长度或 j 等于 needle 的长度为止;
- 若 j 等于 needle 的长度,则输出 i - j;反之则输出 -1;
三、解题过程
-
实现计算 needle 字符串前缀表接口函数
void getNext(char* s, int* next, int sLen){
int j = 0, i = 1;
next[j] = 0;
for(; i < sLen; i++){
while(j - 1 >= 0 && s[j] != s[i]){
j = next[j - 1];
}
if(s[j] == s[i]) j++;
next[i] = j;
}
}
-
找出字符串中第一个匹配项的下标
int strStr(char * haystack, char * needle){
int i = 0, j = 0;
int hLen = strlen(haystack);
int nLen = strlen(needle);
if(nLen == 0) return 0;
int* next = (int*)malloc(sizeof(int) * nLen);
getNext(needle, next, nLen);
for(; i < hLen && j < nLen; i++){
while(j > 0 && haystack[i] != needle[j]){
j = next[j - 1];
}
if(haystack[i] == needle[j]) j++;
}
if(j == nLen) return i - j;
return -1;
}
四、代码
void getNext(char* s, int* next, int sLen){
int j = 0, i = 1;
next[j] = 0;
for(; i < sLen; i++){
while(j - 1 >= 0 && s[j] != s[i]){
j = next[j - 1];
}
if(s[j] == s[i]) j++;
next[i] = j;
}
}
int strStr(char * haystack, char * needle){
int i = 0, j = 0;
int hLen = strlen(haystack);
int nLen = strlen(needle);
if(nLen == 0) return 0;
int* next = (int*)malloc(sizeof(int) * nLen);
getNext(needle, next, nLen);
for(; i < hLen && j < nLen; i++){
while(j > 0 && haystack[i] != needle[j]){
j = next[j - 1];
}
if(haystack[i] == needle[j]) j++;
}
if(j == nLen) return i - j;
return -1;
}
时间复杂度:O(m*n),空间复杂度:O(n)。