题目:
Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
这是算法中比较经典的问题,判断一个字符串是否是另一个字符串的子串。
1. The brute force method
思路:遍历haystack的索引,直到匹配needle子字符串,否则返回-1;
Attention:
1. 注意内层循环对haystack索引的处理,haystack[ i + j ] 既不破坏haystack的匹配起始索引,同时又能保证haystack和needle同步移动。
2. 获取char* haystack 类型字符串的长度方法 strlen(haystack) ; char* haystack调用 haystack[n]
复杂度: 时间O(MN) 空间O(1)
AC Code 1: 执行时间36ms
class Solution {
public:
int strStr(char *haystack, char *needle) {
//如果needle是haystack的子串,返回第一个出现的索引值;如果不是,返回-1
//朴素匹配方法:遍历haystack的索引,直到匹配needle子字符串,否则返回-1;
//The brute force method
//获取char*类型字符串的长度方法 strlen haystack.length()
int n = strlen(haystack);
int m = strlen(needle);
for(int i = 0; i <= n - m; i++)
{
int j = 0;
for(; j < m; j++)
{
//char* haystack调用 haystack[n]
if(haystack[i + j] != needle[j]) break;
}
if( j == m) return i;
}
return -1;
}
};
class Solution {
public:
int strStr(char *haystack, char *needle) {
for(int i = 0; ; i++)
{
for(int j = 0; ; j++)
{
if(j == strlen(needle)) return i;
if(i + j == strlen(haystack)) return -1;
if(needle[j] != haystack[i + j]) break;
}
}
}
};
2. 简易版Boyer-Moore算法
思路:参考《字符串匹配的Boyer-Moore算法》 阮一峰
Attention:
1. 简易版:只使用规则:“后移位数 = 坏字符的位置 - 搜索词中的上一次出现位置”;没有使用“后移位数 = 好后缀的位置 - 搜索词中的上一次出现位置”
2.if(skip < 0) skip = 1;如果搜索词是单字符,会出现j = 0 && skipTable对应值也为0的情况,skip = 0; 所以应该置skip为1.否则会判成成功匹配。
如缺少该句判断:
Input: | "mississippi", "a" |
Output: | 0 |
Expected: | -1 |
AC Code:
class Solution {
public:
//Boyer-Moore算法
//计算坏字符上次出现的位置
void bmSkipTable(char* ch, vector<int> &skipTable)
{
if(!ch) return;
//skipTable.resize(26);
int m = strlen(ch);
//设置搜索词上一次字母出现的位置。若搜索词中不包含的字母为初始值-1.
for(int i = 0; i < m; i++)
{
skipTable[ch[i] - 'a'] = i;
}
}
int strStr(char *haystack, char *needle) {
if(!haystack && !needle) return 0;
int n = strlen(haystack);
int m = strlen(needle);
vector<int> skipTable(26,-1);
bmSkipTable(needle, skipTable);
int skip = 0;
for(int i = 0; i <= n - m; i += skip)
{
skip = 0;
for(int j = m -1; j >= 0; j--)
{
if(haystack[i + j] != needle[j])
{
skip = j - skipTable[needle[j] - 'a'];
//如果搜索词是单字符,会出现j = 0 && skipTable对应值也为0的情况,skip = 0; 所以应该置skip为1.
if(skip < 1) skip = 1;
break;
}
}
if(skip == 0) return i;
}
return -1;
}
};
3.KMP算法
思路:字符串匹配的KMP算法 阮一峰 (备注:还没仔细研究code)
算法复杂度: O(n + m) 12ms
AC Code:
<strong>c</strong>lass Solution {
public:
int strStr(char *haystack, char *needle) {
int haylen = strlen(haystack);
int needlen = strlen(needle);
int* fail = new int[needlen];
memset(fail, -1, needlen * sizeof(int)); // strlen(fail)
int i, j, k;
for (i = 1; i < needlen; ++i) {
for (k = fail[i-1]; k >= 0 && needle[i] != needle[k+1]; k = fail[k]);
if (needle[k+1] == needle[i])
fail[i] = k + 1;
}
i = j = 0;
while(i < haylen && j < needlen) // while(haystack[i] && needle[j])
{
if (haystack[i] == needle[j])
{
++i;
++j;
}
else if(j == 0) ++i;
else j = fail[j-1] + 1;
}
delete fail;
if(j == needlen){
return i - j;
} else {
return -1;
}
}
};