之前刷到jmp的时候给自己整蒙了,直接看睡着了,希望今天再看一遍能有收获。
今日任务
- 28. 实现 strStr()
- 459.重复的子字符串
- 字符串总结
- 双指针回顾
一、实现strStr()
kmp:主要思想:当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。
(此处用于回退的前缀表是next数组)
前缀表:记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。
前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串。
后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。
class Solution {
public:
void getnext(string& s,int* next){
int j = 0;
next[0] = j;
for(int i =1;i<s.size();i++){
while(j>0&&s[i]!=s[j]){
j = next[j-1];
}
if(s[j]==s[i]){
j++;
}
next[i] =j;
}
}
int strStr(string haystack, string needle) {
if(needle.size()==0){
return 0;
}
int next [needle.size()];
getnext(needle,next);
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;
}
};
主打的就是一个没有思路(全忘了)
跟着题解学了一遍,有跟着代码梳理了一遍思路写过了。
二、重复的子字符串
class Solution {
public:
bool repeatedSubstringPattern(string s) {
string ss = s+s;
ss.erase(ss.begin());
ss.erase(ss.end()-1);
if(ss.find(s)!=std::string::npos) return true;
return false;
}
};
移动匹配的代码还是比较简单的,今天的重头戏还是kmp。
class Solution {
public:
void getNext (int* next, const string& s){
next[0] = -1;
int j = -1;
for(int i = 1;i < s.size(); i++){
while(j >= 0 && s[i] != s[j + 1]) {
j = next[j];
}
if(s[i] == s[j + 1]) {
j++;
}
next[i] = j;
}
}
bool repeatedSubstringPattern(string s) {
if(s.size()==0){
return false;
}
int next[s.size()];
getNext(next,s);
int len =s.size();
if(next[len-1]!=-1&&len%(len-(next[len-1]+1))==0){
return true;
}
return false;
}
};
getnext()代码基本没变,是下面的判定条件发生变化。
看完一遍,我有感觉我行了(狗头)
总结总是很重要,带我们回顾写过的代码。