代码随想录刷题随记8-KMP
KMP原理:文章链接
28. 找出字符串中第一个匹配项的下标
标准的kmp类型的题
leetcode链接
cpp
class Solution {
public:
vector<int> getnext(string s){
if(s.size()==1){
return {-1};
}
if(s.size()==2){
return {-1,0};
}
vector<int>next=vector<int>(s.size(),0);
next[0]=-1;
next[1]=0;
int cnt=0;
int x=2;
while(x<s.size()){
if(s[x-1]==s[cnt]){
next[x++]=++cnt;
}
else if(cnt>0){
cnt=next[cnt];
}
else{
next[x++]=0;
}
}
return next;
}
int strStr(string haystack, string needle) {
if(needle.size()>haystack.size())
return -1;
vector<int> next=getnext(needle);
int x=0;
int y=0;
while(x<haystack.size()&&y<needle.size()){
if(haystack[x]==needle[y]){
x++;
y++;
}
else if(y>0){
y=next[y];
}
else{
x++;
}
}
return y==needle.size()? x-y:-1;
}
};
459.重复的子字符串
leetcode 链接
方法1,暴力枚举
我们只需要判断,以第一个字母为开始的子串就可以,所以一个for循环获取子串的终止位置就行了。 而且遍历的时候 都不用遍历结束,只需要遍历到中间位置,因为子串结束位置大于中间位置的话,一定不能重复组成字符串。复杂度 O ( N 2 ) O(N^2) O(N2)
解题代码:
cpp
class Solution {
public:
bool repeatedSubstringPattern(string s) {
for(int i=1;2*i<=s.size();i++){
if(s.size()%i==0){
bool match=true;
for(int j=i;j<s.size();j++){
if(s[j]!=s[j-i]){
match=false;
break;
}
}
if(match)
return match;
}
}
return false;
}
};
方法2
我们将两个 sss 连在一起,并移除第一个和最后一个字符。如果 sss 是该字符串的子串,那么 sss 就满足题目要求。
其中判断是否为字串采用kmp算法
解题代码:
cpp
class Solution {
public:
bool repeatedSubstringPattern(string s) {
return (s + s).find(s, 1) != s.size();
}
};
方法三kmp
活用kmp的前后缀匹配思想
在由重复子串组成的字符串中,最长相等前后缀不包含的子串就是最小重复子串,这里拿字符串s:abababab 来举例,ab就是最小重复单位
数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。
解题代码:
cpp
class Solution {
public:
vector<int> getnext(string s){
if(s.size()==1){
return {-1};
}
if(s.size()==2){
return {-1 ,0};
}
vector<int> next=vector<int>(s.size()+1,0);
next[0]=-1;
next[1]=0;
int x=2;
int cnt=0;
while(x<s.size()+1&&cnt<s.size()){
if(s[x-1]==s[cnt]){
next[x++]=++cnt;
}
else if(cnt>0){
cnt=next[cnt];
}
else{
next[x++]=0;
}
}
return next;
}
bool repeatedSubstringPattern(string s) {
if(s.size()<=1)
return false;
if(s.size()==2){
return s[0]==s[1];
}
vector<int> next=getnext(s);
int sublen=next[s.size()];
int len=s.size();
return (sublen!=0)&&(len%(len-sublen)==0)? true:false;
}
};