28. 实现 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
示例 3:
输入:haystack = "", needle = ""
输出:0
提示:
-
0 <= haystack.length, needle.length <= 5 * 104
-
haystack 和 needle 仅由小写英文字符组成
题解
思路:本题是典型的 KMP 算法题,利用 KMP 算法解答可获得 O(M+N) (M为文本串的长度,N为模式串的长度) 的计算开销。如果使用暴力法,则计算开销为 O(M*N)。
注意:构造prefix数组其实就是计算模式串s,前缀表的过程。主要有如下三步:
-
初始化
-
处理前后缀不相同的情况
-
处理前后缀相同的情况
代码(C++)
//KMP算法——构造前缀表(最长前缀长度减一) void getPrefix(int *prefix, string needle) { int j = -1; prefix[0] = j; // i 是从1开始的 for (int i = 1; i < needle.size(); i++) { //前后缀不一样 while (j >= 0 && needle[i] != needle[j+1]) { j = prefix[j]; } //前后缀一样 if (needle[i] == needle[j+1]) { j++; } prefix[i] = j; //将(前缀长度)j 赋值给prefix[i] } } int strStr(string haystack, string needle) { if (needle.size() == 0) { return 0; } int prefix[needle.size()]; getPrefix(prefix, needle); int j = -1;//用来遍历needle,j的初值为-1是因为prefix数组里面记录的起始位置是 -1 int i = 0;//用来遍历haystack for (; i < haystack.size(); i++) { //不匹配,回退 while (j >= 0 && haystack[i] != needle[j+1]) { j = prefix[j]; } //匹配,i,j 同时向后移动 if (haystack[i] == needle[j+1]) { j++; } //找到needle if (j == (needle.size() - 1)) { return (i - needle.size() + 1); } } return -1; }
分析
-
时间复杂度:O(M+N)
-
参考链接