1.BF算法是笔试面试题,一定要能够写出
2.BMP算法是面试题,一定要可以自己描述出算法思想
3.BF算法的i每次回退到刚才位置的下一个位置(即i-j+1),j每次回退到0
4.KMP算法的i不回退(这是重点),j退到该退的位置k
5.next数组的长度和子串的长度一样,保存的是子串失配时每一个位置对应的k值,即要回退到的地方的下标
6.主串(s) 子串§
BF算法(笔试面试重点题)
朴素(简单)查找算法:失配时,i回退到刚才起始位置的下一个位置,j回退到0
笔试面试重点题,时间复杂度为O(n*m),空间杂度为O(1)
代码
int BF(const char* str, const char* sub, int pos)//笔试重点题 O(n*m),O(1)
{
//参数判断
assert(str != NULL && sub != NULL);
if(str == NULL || sub == NULL)
return -1;
int lenstr = strlen(str);//主串长度
int lensub = strlen(sub);//子串长度
if (pos < 0 || pos >= lenstr)
return -1;
int i = pos;//主串下标
int j = 0;//子串下标
while (i < lenstr && j < lensub)//没有比对完
{
if (str[i] == sub[j])//匹配成功,一起往前走
{
i++;
j++;
}
else//匹配失败(失配)
{
i = i - j + 1;//i回退到刚才起始位置的下一个位置
j = 0;//j回退到0
}
}
if (j >= lensub)//子串完成,说明找到了,只能通过子串来判断是否完成
return i - j;//找到了,返回第一个匹配成功的下标
else
return -1;//失配了,返回-1
}
int main()
{
printf("%d\n",BF("ababcabcdabcde","abcd",0));//5
printf("%d\n",BF("ababcabcdabcde","abcd",6));//9
printf("%d\n",BF("ababcabcdabcde","abcd",10));//-1
return 0;
}
KMP算法(不笔试只面试)
KMP查找算法:特点,i不需要回退,j退到该退的位置k
笔试面试重点题,时间复杂度为O(n+m),空间复杂度为O(m)(m长度的next数组)
代码
static void GetNext(const char* sub, int* next)
{
//参数判断
assert(sub != NULL || next != NULL);
if(sub == NULL || next == NULL)
return ;
int lensub = strlen(sub);
if (lensub <= 1)
{
next[0] = -1;//必须有,比如"abc","c"这个例子
return;
}
next[0] = -1;
next[1] = 0;
int j = 1;
int k = 0;
while (j + 1 < lensub)//根据next[j]求next[j+1]
{
if (k==-1 || sub[k] == sub[j])//如果下一个字符相等
{
next[++j] = ++k;
/*next[j + 1] = k + 1;
++j;
++k;*/
}
else
{
k = next[k];
}
}
}
//KMP算法,特点是i不需要回退,其时间复杂度为O(n+m).不笔试只面试
int KMP(const char* str, const char* sub, int pos)//面试重点题,时间复杂度O(n+m),空间复杂度O(1)
{
assert(str != NULL && sub != NULL);
if(str == NULL || sub == NULL)
{
return -1;
}
int lenstr = strlen(str);//主串长度
int lensub = strlen(sub);//子串长度
if (pos < 0 || pos >= lenstr)
return -1;
int i = pos;//主串下标
int j = 0;//子串下标
int* next = (int *)malloc(lensub*sizeof(int));//创建一个和字串长度一样的动态数组,用来保存字符串失配的所有位置对应的k值
GetNext(sub,next);//获得每一个位置的k值
assert(next != NULL);
while (i < lenstr && j < lensub)
{
if (j==-1 || str[i] == sub[j])//匹配成功
{
i++;
j++;
}
else//匹配失败(失配)和BF算法不同
{
//i不回退,j退到该退的位置k
j = next[j];//j = k;
}
}
free(next);
if (j >= lensub)//子串完成,说明找到了,只能通过子串来判断是否完成
return i - j;//找到了,返回第一个匹配成功的下标
else
return -1;//失配了,返回-1
}
int main()
{
printf("%d\n",KMP("ababcabcdabcde","abcd",0));//5
printf("%d\n",KMP("ababcabcdabcde","abcd",6));//9
printf("%d\n",KMP("ababcabcdabcde","abcd",10));//-1
printf("%d\n",KMP("abc","c",0));//2
return 0;
}