给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle
不是 haystack
的一部分,则返回 -1
。
示例 1:
输入:haystack = "sadbutsad", needle = "sad" 输出:0 解释:"sad" 在下标 0 和 6 处匹配。 第一个匹配项的下标是 0 ,所以返回 0 。
这题如果用substr其实很简单:从字符串首位开始遍历,截取与needle相同大小的字符串进行比较,如果相同则返回i;后面看了卡哥讲解的KMP算法,说实话有点整晕了,归纳了下在本题中应用大致就是先把needle的最长相等前后缀数组next给算出来,然后应用kmp算法的思想比较haysatck和needle字符:遍历haystack,while j>0 && haystack[i] !=needle[j],则j = next[j-1],如果aystack[i] ==needle[j] j++;最后如果j == needle.size() - 1, 则证明匹配,返回相应位置 i-needle.size() + 1,j指向前缀末尾,i指向后缀末尾另,KMP算法主要归纳为以下四步:
1、初始化:定义j(前缀末尾,一般从位置0开始),i(后缀末尾,一般从位置1开始),next数组(数组首位等于j)
2、处理前后缀不相同的情况:while(j>0 && s[i] !=s[j]),j = next[j-1];这里是判断如果前缀和后缀不相等时,前缀前移,最多到字符串首位位置,所以用while;
3、处理前后缀相同的情况:两者相同,同时i++、j++就好
4、将j(前缀的长度)赋给next[i], 因为next[i]要记录相同前后缀的长度
// 暴力
class Solution {
public:
int strStr(string haystack, string needle) {
if(haystack.size() < needle.size()) return -1;
for(int i = 0; i <= haystack.size() - needle.size(); i++) {
if(haystack.substr(i, needle.size()) == needle) return i;
}
return -1;
}
};
// kmp
class Solution {
public:
void getNext(int* next, string& s) {
int j = 0;
next[0] = 0;
for(int i = 1; i < s.size(); i++) {
while(j>0 && s[i] != s[j]) {
j = next[j-1];
}
if(s[i] == s[j]) j++;
next[i] = j;
}
}
int strStr(string haystack, string needle) {
if(haystack.size() < needle.size()) return -1;
int next[needle.size()];
getNext(next, needle);
int j = 0;
for(int i = 0; i < haystack.size(); i++) {
while(j > 0 && haystack[i] != needle[j]) j = next[j-1];
if(haystack[i] == needle[j]) j++;
if(j == needle.size()) return (i - needle.size() + 1);
}
return -1;
}
};
给定一个非空的字符串 s
,检查是否可以通过由它的一个子串重复多次构成。
示例 1:
输入: s = "abab" 输出: true 解释: 可由子串 "ab" 重复两次构成。
说实话,晕了,完全没搞明白怎么用KMP做,后面看卡哥视频讲解才知道在求出next数组后,字符串的长度如果能整除字符串中不包含最长公共前后缀的那一部分长度,则证明该字符串由字串重复两次构成,需要再多看多领悟,KMP算法还是没搞太懂
class Solution {
public:
void getNext(int* next, string& s) {
int j = 0;
next[0] = 0;
for(int i = 1; i while(j > 0 && s[i] != s[j]) j = next[j-1]; if(s[i] == s[j]) j++; next[i] = j; } } bool repeatedSubstringPattern (string s) { if (s.size() == 0) { return false; } int next[s.size()]; getNext(next, s); for (auto c : next) cout << c << endl; int len = s.size(); if (next[len - 1] != 0 && len % (len - next[len - 1]) == 0) { return true; } return false; } };