两个题目都属于KMP算法的应用,我是个菜鸟,目前只能理解算法的原理,但还没办法复现代码,所以只能看答案来学习了。
28. 实现 strStr()
class Solution {
public:
int strStr(string haystack, string needle) {
int n = haystack.size(),m = needle.size();
if (m == 0){
return 0;
}
vector<int> next(m,-1);
for (int i = 1; i < m; i++){
int j = next [i-1];
while (j > -1 && needle[i] != needle[j+1]){
j = next[j];
}
if (needle[i] == needle[j+1]){
next[i]=j+1;
}
}
for (int i = 0, j = -1; i < n; i++){
while (j > -1 && haystack[i] != needle[j+1]){
j = next[j];
}
if (haystack[i] == needle[j+1]){
j++;
}
if (j+1 == m){
return i-m+1;
}
}
return -1;
}
};
459.重复的子字符串
这里使用了一个小结论,即s+s中一定会出现s的组合(s+s不从第一位开始),由此得到代码
class Solution {
public:
bool kmp(const string& s,const string& t){
int n = s.size() , m = t.size() ;
vector<int> next(m,-1);
for (int i = 1; i < m; i++){
int j = next [i-1];
while (j > -1 && t[i] != t[j+1]){
j = next[j];
}
if (t[i] == t[j+1]){
next[i] = j+1;
}
}
int j = -1;
for (int i = max(m/2,1); i < n-1; i++){
while (j != -1 && s[i] != t[j+1]){
j = next[j];
}
if (s[i] == t[j+1]){
j++;
if (j == m-1){
return true;
}
}
}
return false;
}
bool repeatedSubstringPattern(string s) {
return kmp(s+s,s);
}
};
还有一种方法是对于KMP算法中next数组理解比较深,则可以利用next数组来判断,即
len % (len - (next[len - 1] + 1)) == 0 ,则说明数组的长度正好可以被 (数组长度-最长相等前后缀的长度) 整除 ,说明该字符串有重复的子字符串。即最大相等前缀和最大相等后缀所错开的几个元素就是重复字符串。
代码如下
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;
}
};