实现strStr
KMP算法的主要思想:
当字符串出现不匹配时,可以知道之前匹配过的一部分内容,避免字符串从头开始匹配。(不理解的可以从b站上看奇乐编程学院)
明确KMP中每个字母及单词的含义:
next:模式串的前缀表。
s:代表文本串。
p:代表模式串。
i:代表文本的下标。
j:代表模式串的下标。
m:用于比较模式串和文本串是否相同。
28. 找出字符串中第一个匹配项的下标
给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle
不是 haystack
的一部分,则返回 -1
。
示例 1:
输入:haystack = "sadbutsad", needle = "sad" 输出:0 解释:"sad" 在下标 0 和 6 处匹配。 第一个匹配项的下标是 0 ,所以返回 0 。
示例 2:
输入:haystack = "leetcode", needle = "leeto" 输出:-1 解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。
方法一:暴力解法 。
class Solution {
public:int strStr(string s, string p) {int n = s.size(), m = p.size();for(int i = 0; i <= n - m; i++){int j = i, k = 0; while(k < m && s[j] == p[k]){j++;k++;}if(k == m) return i;}return -1;}
};
使用双层循环。定义两个int类型的变量m,n,分别用来记录文本串s和模式串p的长度。 当i大于零且小于文本串减模式串长度时,进入外层循环。定义一个变量j,将j初始化为i,定义一个变量k,将k初始化为0。的如果k小于m且以j为下标的文本串对应的值等于以k为下标对应的模式串的值时,进入内层循环。j加加,k加加。跳出内层循环。如果k==m。则返回i。跳出外层循环。返回-1。
方法二:KMP方法调用函数 。
class Solution {
public:void getNext(int* next, const string& m) {int j = 0;next[0] = 0;for(int i = 1; i < m.size(); i++) {while (j > 0 && m[i] != m[j]) {j = next[j - 1];}if (m[i] == m[j]) {j++;}next[i] = j; }}int strStr(string s, string p) {if (p.size() == 0) {return 0; }int next[p.size()];getNext(next, p);int j = 0;for (int i = 0; i < s.size(); i++) {while(j > 0 && s[i] != p[j]) {j = next[j - 1];}if (s[i] == p[j]) {j++;}if (j == p.size()) {return (i - p.size() + 1);}}return -1;}
};
创建一个void类型的子函数命名为getNext。函数接收一个指向int类型数组的指针next,以及一个常量引用的字符串m。定义一个变量j表示模式串的下标初始化为0,初始化next数组的第一个元素为0。遍历模式串m,从第二个字符开始,计算每个位置对应的next。当j大于0且当年字符m[j]与m[i]不相等时,通过next数组回溯j的位置,目的是找到一个合适的j,使得从该位置开始能继续匹配。回溯j的位置,利用好已经计算好的next值,让j跳到合适的位置继续匹配。如果当前字母m[i]与m[j]相等,j加加。将当前位置i的最长前后缀记录到next数组中。创建一个int类型的主函数,用于在文本串s中定义查找p的首次出现的位置,接受文本串s和模式串p作为参数。如果模式串p的长度为0,则返回0。定义一个int类型的数组next,用于存储模式串p的前缀表。调用getNext计算模式串p的前缀表。定义一个变量j,并初始化为0。遍历文本串s,从第一个字符开始寻找模式串p。当j大于0且当前文本串s[i]不等于模式串p[j]。回溯j的位置,利用next数组调整j,以便继续匹配。如果当前文本串s[i]等于模式串p[j],j加加。如果j等于模式串p的长度说明找到了完整的模式串。返回模式串在文本串中首次出现的位置。跳出循环。返回-1。
方法三:KMP方法。
class Solution {
public:int strStr(string s, string p) {if (p.size() == 0) {return 0;}int n = s.size();int m = p.size();int next[m];int j = 0;next[0] = 0;for (int i = 1; i < m; i++) {while (j > 0 && p[i] != p[j]) {j = next[j - 1];}if (p[i] == p[j]) {j++;}next[i] = j;}j = 0;for (int i = 0; i < n; i++) {while (j > 0 && s[i] != p[j]) {j = next[j - 1];}if (s[i] == p[j]) {j++;}if (j == m) {return (i - m + 1);}}return -1;}
};