来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-strstr
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例 1:
输入: haystack = “hello”, needle = “ll”
输出: 2
示例 2:
输入: haystack = “aaaaa”, needle = “bba”
输出: -1
解题方法:
1)暴力解法
双重循环
2)双指针
class Solution {
public:
int strStr(string haystack, string needle) {
if (needle.size() == 0)
return 0;
if (needle.size() > haystack.size())
return -1;
int j = 0;
int i = 0;
for (i = 0; i < haystack.size(); i++)
{
if (haystack[i] == needle[j])
{
if (j == needle.size()-1)
return i - j;
j ++;
}
else
{
i -= j;
j = 0;
}
}
return -1;
}
};
3)KMP解法
class Solution {
public:
int strStr(string haystack, string needle) {
int n = needle.size();
if (n == 0)
return 0;
return prefix_search(haystack, needle);
// return -1;
}
void prefix_table(string needle, int* prefix, const int n) {
int len = 0;
prefix[0] = 0;
int i = 1;
while (i < n) {
if (needle[i] == needle[len]) { // 字符串的第len个与第i个元素进行比较
len ++;
prefix[i] = len;
i ++;
}
else { // 不等的话将len的值置为prefix[len-1]
if (len > 0) {
len = prefix[len - 1];
}
else {
prefix[i] = len; // 这里len为0
i ++;
}
}
}
}
void move_prefix(int* prefix, const int n) {
for (int i = n - 1; i > 0; i --) {
prefix[i] = prefix[i - 1];
}
prefix[0] = -1;
}
int prefix_search(string text, string pattern) {
int n = pattern.size();
int* prefix = new int[n];
prefix_table(pattern, prefix, n);
move_prefix(prefix, n);
int i = 0, j = 0;
int m = text.size();
while(i < m) {
if (j == n - 1 && pattern[j] == text[i])
return i - j;
if (pattern[j] == text[i]) {
i ++;
j ++;
}
else {
j = prefix[j];
if (j == -1) {
i ++; j ++;
}
}
}
return -1;
}
};
- Rabin Karp解法
// 使用Rabin Karp算法求解
class Solution {
public:
static const int BASE = 1000000;
public:
int strStr(string haystack, string needle) {
if (needle.size() == 0)
return 0;
if (needle.size() > haystack.size())
return -1;
int m = needle.size();
// 31^m
int power = 1;
for (int i = 0; i < m; i ++)
power = (power * 31) % BASE;
// needle字符的hash值
int targetCode = 0;
for (int i = 0; i < m; i ++)
targetCode = (targetCode * 31 + needle[i]) % BASE;
// 当前字符串的hash值
int hashCode = 0;
for (int i = 0; i < haystack.size(); i ++) {
// abc + d
hashCode = (hashCode * 31 + haystack[i]) % BASE;
if (i < m - 1)
continue;
// abcd - a
if (i >= m) {
hashCode = (hashCode - haystack[i - m] * power) % BASE;
// 保证为正数
if (hashCode < 0)
hashCode += BASE;
}
// double check the string
if (hashCode = targetCode) {
if (haystack.substr(i - m + 1, m).compare(needle) == 0)
return i - m + 1;
}
}
return -1;
}
};