Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
It is pretty hard to generalize KMP algorithm under stress and limited time. Better to formalize brute force first and then move forward to KMP.
#include
#include
#include
using namespace std;
// brute force
int strStr(string haystack, string needle) {
int m = haystack.size();
int n = needle.size();
int i = 0, j = 0;
while(i < m && j < n) {
if(haystack[i] == needle[j]) {
i++;
j++;
} else {
i = i - j + 1;
j = 0;
}
}
return j == n ? i - j : -1;
} // time complexity: O(m*n)
// KMP to make the time complexity to be O(m + n);
vector next(string& needle) {
vector next(needle.size(), 0);
for(int i = 1; i < needle.size(); ++i) {
int j = next[i-1];
while(j > 0 && (needle[i] != needle[j])) j = next[j-1];
next[i] = (j + (needle[i] == needle[j]));
}
return next;
}
int strStrII(string haystack, string needle) {
vector nextV = next(needle);
int k = 0;
for(int i = 0; i < haystack.size(); ++i) {
while(k > 0 && haystack[i] != needle[k]) k = nextV[k-1];
if(haystack[i] == needle[k]) k++;
if(k == needle.size()) return i - needle.size() + 1;
}
return -1;
}
One Variation in Facebook interview.
/*
StrStr variation.
implement function strstr(string a, string b) return index where any permutation
of b is a substring of a.
eg:
strstr("hello", "ell") return 1
strstr("hello", "lle") return 1
strstr("hello", "wor") return -1;
*/
void permutate(string target, string path, set& res) {
if(target.size() == 0) {
res.insert(path);
return;
}
for(int i = 0; i < target.size(); ++i) {
string remains = target.substr(0, i) + target.substr(i + 1);
permutate(remains, path + target[i], res);
}
}
set permutate(string target) {
string path = "";
set res;
permutate(target, path, res);
return res;
}
int strstr(string orig, string target) {
set perm = permutate(target);
auto iter = perm.begin();
int k = target.size();
for(int i = 0; i < orig.size() - k; ++i) {
string tmp = orig.substr(i, k);
if(perm.find(tmp) != perm.end()) return i;
}
return -1;
}
int main(void) {
cout << strstr("hello", "ell") << endl;
cout << strstr("hello", "lle") << endl;
cout << strstr("hello", "wor") << endl;
}
Facebook has a variation related question: 两个string,如果第二个在第一个里没有出现return-1,如果出现了return最后一次出现时候在第一个string里的position
This is a variation to KMP algorithm. We just need to reverse the str and the pattern, apply KMP. The tricky part is to find the right index.
Another variation:
Suppose the given haystack is a matrix, the pattern string is a normal string. Return the start index otherwise return -1
#include "header.h"
using namespace std;
// strstr follow up. The input string is a 2D array.
/*
For example,
Give:
[[a, b, c, c]
[c, b, d, e]
]
Needle: [c, c, b, d] return 2.
Needle: [b, d] return 5.
*/
vector getPrefix(string pattern) {
int n = pattern.size();
vector next(n, 0);
int i = 1, j = 0;
while(i < n) {
j = next[i-1];
while(j > 0 && (pattern[i] != pattern[j])) j = next[j-1];
next[i] = (j + pattern[i] == pattern[j]);
i++;
}
return next;
}
char getMatrixChar(vector< vector >& matrix, int i) {
int cols = matrix[0].size();
return matrix[i / cols][i % cols];
}
int findTargetInMatrix(vector< vector >& matrix, string pattern) {
int rows = matrix.size();
int cols = matrix[0].size();
int i = 0, j = 0;
vector next = getPrefix(pattern);
while(i < rows*cols) {
char tmp = getMatrixChar(matrix, i);
while(j > 0 && (tmp != pattern[j])) j = next[j-1];
if(tmp == pattern[j]) {j++;}
i++;
if(j == pattern.size()) return i - pattern.size();
}
return -1;
}
int main(void) {
vector< vector > matrix {
{'a', 'b', 'c', 'c'},
{'c', 'b', 'd', 'e'}};
cout << findTargetInMatrix(matrix, "cccb") << endl;
}