基础数据结构13:字符串匹配(BF和KMP算法)

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……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值