28. 实现 strStr()
题目链接
KMP算法
前缀表版
class Solution {
public:
void getNext(int* next,string s){
next[0]=0;
int j=0;//前缀末尾下标。前缀:不包含最后一个字符
for(int i=1;i<s.size();i++){//后缀末尾下标。后缀:不包含第一个字符
//每次循环,考虑当前前后缀末尾是否匹配
while(j>0 && s[i]!=s[j]){//不匹配的情况
j=next[j-1];//j退到前一个
}
if(s[i]==s[j])
j++;//比较下一个后缀末尾
next[i]=j;//此时,j后移,恰好为最长前后缀的“长度”
//同时也是上一个最长相等前后缀的下一个待比较的下标
}
}
int strStr(string str, string sub) {
int next[sub.size()];
getNext(next,sub);
int j=0;//子串下标
for(int i=0;i<str.size();i++){
while(j>0&&str[i]!=sub[j]){
j=next[j-1];
}
if(str[i]==sub[j]){
j++;
}
if (j == sub.size() ) {
return (i - sub.size() + 1);
}
}
return -1;
}
};
统一减一版
next[i] 表示 i(包括i)之前最长相等的前后缀长度(其实就是j)
class Solution {
public:
void getNext(int* next,string s){
int j=-1;//修改
next[0]=j;//next[0]=-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;
}
}
int strStr(string str, string sub) {
int next[sub.size()];
getNext(next,sub);
int j=-1;
for(int i=0;i<str.size();i++){
while(j>=0&&str[i]!=sub[j+1]){//修改
j=next[j];//修改
}
if(str[i]==sub[j+1]){//修改
j++;
}
if (j == sub.size()-1) {//修改
return (i - sub.size() + 1);
}
}
return -1;
}
};
459.重复的子字符串
class Solution {
public:
void getNext(int* next,string s){
next[0]=0;
int j=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;
}
}
bool repeatedSubstringPattern(string s) {
int len=s.size();
int next[len];
getNext(next,s);
if(next[len-1]!=0&& len%(len-next[len-1])==0){//len-next[len-1]:最小子串的长度
return true;
}
return false;
}
};