- 实现 strStr()
实现 strStr() 函数。
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。
说明:
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。
示例 1:
输入:haystack = “hello”, needle = “ll”
输出:2
示例 2:
输入:haystack = “aaaaa”, needle = “bba”
输出:-1
提示:
1 <= haystack.length, needle.length <= 104
haystack 和 needle 仅由小写英文字符组成
思路:
方法一:使用两层for循环进行匹配
方法二:使用KMP算法进行匹配,主要是前缀表计算和匹配方法的实现。前缀表计算需要明白前缀和后缀是什么含义,然后进行计算
上代码了~
// 方法一 先来个暴力算法提神醒脑 算法时间复杂度O(n*m)
int strStr(char * haystack, char * needle){
int hlen = strlen(haystack);
int nlen = strlen(needle);
int i, j;
int flag;
int ans = -1;
for (i = 0; i < hlen - nlen + 1; i++) {
flag = 0;
for (j = 0; j < nlen; j++) {
if (haystack[i + j] != needle[j]) {
flag = 1;
break;
}
}
if (flag == 0) {
ans = i;
break;
}
}
return ans;
}
// 方法二 KMP算法 算法时间复杂度O(n+m)
//字符串匹配,KMP算法
// 1、计算前缀表next
// 2、如何进行匹配
// 3、如果文本串长度为0,返回0
void getNext(char* needle, int* next) {
int j = 0;// 表示前缀的末尾
next[0] = 0;
int i;// 表示后缀的末尾
int nlen = strlen(needle);
for (i = 1; i < nlen; i++) {
// 如果前后缀两个字符不相等, 进行回退
while(j > 0 && needle[i] != needle[j]) {
j = next[j - 1];
}
// 如果前后缀两个字符相等
if (needle[i] == needle[j]) j++;
// 刷新next
next[i] = j;
}
}
int strStr(char * haystack, char * needle){
// 获取两个字符串的长度
int hlen = strlen(haystack);
int nlen = strlen(needle);
if (hlen == 0) return 0;
// 申请next数组
int* next = (int*)malloc(sizeof(int) * nlen);
// 计算前缀表next
getNext(needle, next);
// 进行字符串匹配
int i;
int j = 0;
for (i = 0; i < hlen; i++) {
// 如果两个字符不相等,进行回退
while (j > 0 && haystack[i] != needle[j]) {
j = next[j - 1];
}
// 如果两个字符相等,移动到下一个字符进行匹配
if (haystack[i] == needle[j]) j++;
// 如果已经匹配完成,那么返回匹配的结果
if (j == nlen) {
return i - nlen + 1;
}
}
free(next);
next = NULL;
return -1;
}
总结:第一次实现完整的kmp算法,鼓掌~
1、本来以为算法很难,但是实际上实现很简单,不要被神秘感吓到了
2、后面多使用kmp算法,尽量快速掌握该算法
3、练习需要连续不断,每日不断练习,不间断的进行总结