1.
2.BF_KMP算法
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(disable:4018)
/*
一定得会的知识:
1.主串i为什么打死不回退
2.next数组只跟子串有关
3.给一个字符串,一定得会手写它的next数组的值
4.BF算法一定得会写
*/
//朴素算法 BF算法 :1.同时向后跑 2.如果相等i++ j++ 3.如果不相等i=i-j+1 j=0
int BF_Search(const char* str, const char* sub, int pos)//从主串的pos下标开始向后找字串
{
assert(str != NULL && sub != NULL && pos >= 0 && pos < strlen(str));
if (str == NULL || sub == NULL || pos < 0 || pos >= strlen(str))
{
return -1;
}
int lenstr = strlen(str);//lenstr 保存主串的长度
int lensub = strlen(sub);//lensub 保存字串的长度
int i = pos; //i 保存主串匹配是的下标
int j = 0; //j 保存子串匹配是的下标
while (i < lenstr && j < lensub)//当主串和字串都没有走出范围的时候,循环继续
{
if (str[i] == sub[j])//如果相等 则i和j同时++, 判断下一个字符
{
i++;
j++;
}
else //代表失配 如果失配 则让i回退到这一次匹配前的位置的下一位 而j归零
{
i = i - j + 1;//
j = 0;//这两行代码顺序不能反
}
}
//此时while循环结束 则只有两种可能 你需要判断i和j谁走到了尾巴
if (j >= lensub)//如果字串j走到了尾巴 代表匹配成功了
{
return i - j;//如果匹配成功 则返回这一次成功匹配前的位置
}
//如果字串j没走到尾巴 那代表主串没有字串想要的 则返回-1
return -1;
}
int* Get_next(const char* sub)//next数组只跟子串有关
{
//assert
int lensub = strlen(sub);//lensub保存子串的长度
int* next = (int*)malloc(sizeof(int) * lensub);//申请一个等长的next数组来保存其每一个K值
assert(next != NULL);
next[0] = -1;//next数组的前两个空间有固定的值 -1 0
next[1] = 0;
int j = 1;//j保存的已知k的下标
int k = 0;
//通过已知推未知 j是已知 则j+1是未知 而j+1的合法性做判断(让j+1<lensub即可)
while (j + 1 < lensub)//给next数组每一个空间都赋合适的值
{
if ((k == -1) || sub[j] == sub[k])//两个相等或者k回退到-1
{
next[++j] = ++k;
/*k++;
j++;
next[j] = k;*/
}
else
{
k = next[k];//k回退到合适的位置
}
}
return next;//将malloc申请来的next数组扔出去
}
int KMP_Search(const char* str, const char* sub, int pos)//从主串的pos下标开始向后找字串
{
assert(str != NULL && sub != NULL && pos >= 0 && pos < strlen(str));
if (str == NULL || sub == NULL || pos < 0 || pos >= strlen(str))
{
return -1;
}
int lenstr = strlen(str);//lenstr 保存主串的长度
int lensub = strlen(sub);//lensub 保存字串的长度
int i = pos; //i 保存主串匹配是的下标
int j = 0; //j 保存子串匹配是的下标
int* next = Get_next(sub);//next数组只跟子串有关
while (i < lenstr && j < lensub)//当主串和字串都没有走出范围的时候,循环继续
{
if ((j == -1) || str[i] == sub[j])//如果相等 则i和j同时++, 判断下一个字符
{
i++;
j++;
}
else //代表失配 如果失配 则让i回退到这一次匹配前的位置的下一位 而j归零
{
//i = i-j+1;//
//j = 0;//这两行代码顺序不能反
j = next[j];//j回到到合适的位置next[j]
}
}
//此时while循环结束 则只有两种可能 你需要判断i和j谁走到了尾巴
if (j >= lensub)//如果字串j走到了尾巴 代表匹配成功了
{
return i - j;//如果匹配成功 则返回这一次成功匹配前的位置
}
//如果字串j没走到尾巴 那代表主串没有字串想要的 则返回-1
return -1;
}
int main()
{
const char* str = "ababcabcdabcde";//主串
const char* sub = "abcd";
/*int tmp = BF_Search(str, sub, 11);
printf("%d\n", tmp);*/
int tmp = KMP_Search(str, sub, 0);
printf("%d\n", tmp);
return 0;
}
3.1.时间空间复杂度,线性表,双向链表,循环链表,串:空串,空格串,字串,真字串, 栈,队列,哈希,排序算法:选择排序,冒泡,快排,堆排,插入排序,希尔排序,归并,基数排序。
2.字符串匹配:BF(朴素算法) KMP算法(最经典的)
3.字符串比较:BF算法:让主串和字串同时向后跑,如果相等向后走,如果不相等,
3.BF算法和KMP算法的区别:i是否回退
BF算法的优缺点:优点:简单易实现。缺点:时间复杂度太高
KMP算法:经典,时间复杂度低,主串的i不会回退。
4.求next数组的方法:-10……