28. 实现 strStr()

180 阅读1分钟

题目描述

实现 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

示例 3:
输入:haystack = "", needle = ""
输出:0

提示:
0 <= haystack.length, needle.length <= 5 * 104
haystack 和 needle 仅由小写英文字符组成

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/im…

实现

  • 方法1 最基础的方法,两层循环,时间复杂度O(m*n)
int strStr(char *haystack, char *needle)
{
    if (strlen(needle) == 0) {
        return 0;
    }
    if (strlen(haystack) == 0) {
        return -1;
    }
    if (strlen(haystack) < strlen(needle)) {
        return -1;
    }
    for (int i = 0; i < strlen(haystack); i++) {
        if (strlen(haystack) - i < strlen(needle)) {    // 没有这个优化会超时
            return -1;
        }
        for (int j = 0; j < strlen(needle); j++) {
            if (haystack[i + j] != needle[j]) {
                break;
            }
            if (j == strlen(needle) - 1) {         // 还没有退出,说明符合,返回i
                return i;
            }
        }
    }
    return -1;
}
  • 方法2 KMP KMP 参考 KMP
void getNext(int *next, char *needle)
{
    // j指向前缀末尾位置,i指向后缀末尾位置
    int j = 0;     // next数组记录的起始位置为-1
    next[0] = j;

    // next[i]表示i之前(包括i)最长相等的前后缀长度(其实就是j)
    for (int i = 1; i < strlen(needle); 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)
{
    if (strlen(needle) == 0) {
        return 0;
    }
    if (strlen(haystack) == 0 || strlen(haystack) < strlen(needle)) {
        return -1;
    }
    
    int next[strlen(needle)];
    getNext(next, needle);
    
    // 下标j指向模式串(needle)起始位置,i指向文本串(haystack)起始位置
    int j = 0;
    for (int i = 0; i < strlen(haystack); i++) {
        while (j > 0 && haystack[i] != needle[j]) {
            j = next[j-1];
        }

        if (haystack[i] == needle[j]) {
            j++;
        }

        if (j == strlen(needle)) {
            return (i - strlen(needle) + 1);
        }
    }
    return -1;
}