IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 2022.4.24 BF和KMP算法 -> 正文阅读

[C++知识库]2022.4.24 BF和KMP算法

1. 字符串中的真子串和子串概念

字符串:“abcd”
真子串:“a”,“b”,“c”,“d”,“ab”,“bc”,“cd”,“abc”,“bcd”
子串:" ",“a”,“b”,“c”,“d”,“ab”,“bc”,“cd”,“abc”,“bcd”,“abcd”
真子串:n*(n+1)/2 ; 子串:n*(n+1)/2 +1

2. BF算法

BF算法(暴力求解)也叫男朋友算法
主串:“ababcabcdabcde”
子串:“abcd”

要在主串里面找子串,如果当前光标在主串的0号位置所指,那么就是返回5;如果光标在主串的7号位置指向,那么就返回9。
第一种BF算法:
在这里插入图片描述
如果i和j指向的字符相同,则i++,j++;如果i和j指向的字符不相同,则j=0,重新开始比较;退出条件:当i或者j向后走,越界了。
因此,看子串在找到还是没找到是只用看j即可,j如果走出自身范围,则找到了,否则没找到。
第二种BF算法:
如果i和j指向的字符相同,则i++,j++;如果i和j指向的字符不相同,则i=i-j+1,j=0;退出条件:如果i或者j走出自身范围(越界),退出之后,我们需要判断到底子串是否在主串中出现与否,只需要判断j即可;j如果走出自身范围,则找到了,return i-j;j如果没有走出自身范围,则没有找到,return -1;
BF算法最经典图:
在这里插入图片描述
代码实现:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>

int BF_Search(const char* str, const char* sub, int pos)//pos代表主串向后搜索的开始位置
{
	assert(str != NULL && sub != NULL && pos >= 0 && pos < strlen(str));
	
	int i = pos;//主串
	int j = 0;//子串
	int len_str = strlen(str);//保存主串有效长度
	int len_sub = strlen(sub);//保存子串有效长度

	while (i < len_str && j < len_sub)
	{
		if (str[i] == sub[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i - j + 1;
			j = 0;
		}
	}
	//此时,当while循环退出,肯定要么找到,要么没找到,只需要通过j判断即可
	if (j < len_sub)
	{
		return -1;//j没有走出自身边界,则没有找到
	}
	else
	{
		return i - j;
	}
}

int main()
{
	const char* str = "ababcabcdabcde";
	const char* sub = "abcd";

	int tmp = BF_Search(str, sub, 0);
	if (tmp >= 0)
	{
		printf("找到了,开始下标为%d\n", tmp);
	}
	else
	{
		printf("没有找到");
	}
	return 0;
}

BF算法的优缺点:
优点:逻辑简单,实现也简单
缺点:效率很低

3.KMP算法

KMP算法就是对BF算法的一个优化
算法:i打死不回退;模式匹配串只与子串有关系

//求子串的模式匹配串next
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
int *Get_Next(const char* sub)
{
	assert(sub != NULL);
	int len = strlen(sub);
	int* next = (int*)malloc(len * sizeof(int));
	assert(next != NULL);//开辟成功
	next[0] = -1;
	next[1] = 0;

	int j = 1;//已知下标,通过已知推未知,j+1代表要推的未知位置
	int k = next[1];
	while (j + 1 < len)//j+1位置得合法
	{
		if (k == -1||sub[j] == sub[k])//如果当前字符和回退的字符相等,将k+1赋值给下一个位置
			                          //或者k==-1,触底了,也是将k+1赋值给下一个位置
		{
			k++;
			j++;
			next[j] = k;
			//或者写为:next[j++]=k++;
		}
		else
		{
			k = next[k];
		}
	}
	return next;

}
//KMP算法
int KMP_Search(const char* str, const char* sub, int pos)
{
	assert(str != NULL && sub != NULL && pos>=0 && pos<strlen(str));

	int i = pos;//主串
	int j = 0;//子串
	int len_str = strlen(str);//保存主串有效长度
	int len_sub = strlen(sub);//保存子串有效长度

	int *next = Get_Next(sub);//此时,子串的模式匹配串获取到

	while (i < len_str && j < len_sub)
	{
		if (j==-1 || str[i] == sub[j])//j如果在第一个字符就失配,这时,只能让i向后走一步i++,j应该指向开始位置(0),但是j现在的值是-1,要变成0需要j++
		{                             //或者i和j指向的字符相等,也是i++,j++
			i++;
			j++;
		}
		else
		{
			//KMP要求i打死不回退,j回到合适的一个位置
			j = next[j];
		}
	}
	//此时,当while循环退出,肯定要么找到,要么没找到,只需要通过j判断即可
	if (j < len_sub)
	{
		return -1;//j没有走出自身边界,则没有找到
	}
	else
	{
		return i - j;
	}
}

int main()
{
	const char* str = "ababcabcdabcde";
	const char* sub = "abcd"; 
	int flag = KMP_Search(str, sub, 0);
	if (flag >= 0)
	{
		printf("找到了,开始下标为%d\n", flag);
	}
	else
	{
		printf("没有找到");
	}
	return 0;
}

运行结果:
在这里插入图片描述

4.BF算法和KMP算法时间复杂度

BF算法:由于会将主串遍历多次,假设最差情况下,整体时间复杂度O(n*m)
KMP算法:由于i打死不回退,只会遍历一遍,整体时间复杂度为O(n+m)
因此,KMP算法是BF算法的优化算法。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 11:24:29  更:2022-04-26 11:25:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 21:59:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码