北邮22信通:利用BF算法解决实际问题:题目实战(超详解)设计函数 char *locatesubstr(char *str1,char *str2)

news2024/12/26 11:19:02

北邮22信通一枚~   

跟随课程进度每周更新数据结构与算法的代码和文章 

持续关注作者  解锁更多邮苑信通专属代码~

获取更多文章  请访问专栏~

北邮22信通_青山如墨雨如画的博客-CSDN博客

目录

题干描述 

解析

1.string库函数

2.使用KMP算法思想

注解1

注解2

注解3


题干描述 

 设计函数 char *locatesubstr(char *str1,char *str2),查找str2指向的字符串在str1指向的字符串中首次出现的位置,返回指向该位置的指针。若str2指向的字符串不包含在str1指向的字符串中,则返回空指针NULL。

注意这里必须使用指针而不是数组下标来访问字符串。

函数接口定义:\n\nchar *locatesubstr(char *str1,char *str2);

其中 str1 和 str2 都是用户传入的参数,其含义如题面所述 。若查找成功则返回指向该位置的指针,若失败则返回空指针。

裁判测试程序样例:

#include <iostream>
using namespace std;
char* locatesubstr(char* str1, char* str2);
int main()
{
    char str1[505], str2[505];
    char* p;
    gets(str1);
    gets(str2);
    p = locatesubstr(str1, str2);
    if (p == NULL) 
        printf("NULL!\n");
    else puts(p);
    return 0;

}

输入样例:

didjfsd dabcxxxxxx

abc

输出样例:

abcxxxxxx

解析

1.string库函数

        首先如果不用KMP算法,我们可以使用C++string库中自带的库函数,也可以轻松解决这道问题,我们来看一下代码:

#include<iostream>
#include<cstring>
using namespace std;
char* locate(char* s, char* e)
{
	string m = s;
	int num = m.find(e);
	if (num == -1)
		throw "non_found";
	//cout << "num=" << num << endl;
	return (s + num);
}
int main()
{
	try
	{
		char a[] = "hello world";
		char b[] = "world";
		char d[] = "print";
		char* result = locate(a, b);
		while (*result != '\0')
			cout << *(result++);
	}
	catch (const char*ss)
	{
		cout << ss << endl;
	}
	return 0;
}

 解释一下:传入两个参数,分别是待查询的字符串和目标子串。然后调用string库中的find函数,寻找子串在主串中的位置,如果没有找到,抛出异常,如果找到了则从这个位置开始,返回剩余全部主串;

2.使用KMP算法思想

char* locatesubstr(char* str1, char* str2)
{
	if (*str2 != '\0')
		while (*str1 != '\0')
		{
			for (int i = 0; *(str1 + i) == *(str2 + i); i++)
				if (*(str2 + i + 1) == '\0')
					return str1;
			str1++;
		}
	return NULL;
}

这段代码看着好像难以理解,我们加一些输出作为调试,来看看效果怎么样:

注解1

#include<iostream>
#include<cstring>
using namespace std;
char* locate(char* s, char* e)
{
	string m = s;
	int num = m.find(e);
	if (num == -1)
		throw "non_found";
	//cout << "num=" << num << endl;
	return (s + num);
}
char* locatesubstr(char* str1, char* str2)
{
	if (*str2 != '\0')
		while (*str1 != '\0')
		{
			for (int i = 0; *(str1 + i) == *(str2 + i); i++)
			{
				cout << "i的值为:" << i << endl;
				if (*(str2 + i + 1) == '\0')
					return str1;
			}
            throw "non_found";
			cout << "str1++" << endl;
			str1++;
		}
	return NULL;
}
int main()
{
	system("color 0A");
	try
	{
		char a[] = "hello world";
		char b[] = "world";
		char d[] = "print";
		char* result = locate(a, b);
		while (*result != '\0')
			cout << *(result++);
		cout << endl;
		char* results = locatesubstr(a, b);
		while (*results != '\0')
			cout << *(results++);
	}
	catch (const char*ss)
	{
		cout << ss << endl;
	}
	return 0;
}

 输出的结果为:

        我们发现,首先,str1++这句代码执行了6次,i的值被修改了5次。 根据代码我们不难发现,这段代码的实现方法是,首先找到和子串首字符相同的字符,看看后面的字符是否也相同

对我们调试程序输入的hello world 所运行出的结果的解释:

首先,i = 0;for循环满足的条件是*str1 == *str2,显然前6个字符都不满足。

根据BF算法,主串向后移动6次;

从第7个字符开始,程序最终进入for循环,继续依次比较子串和主串后面的内容,

因为每次都满足条件*(str1 + i) == *(str2 + i);所以i持续自加,直到自加5次后子串比较完毕,

*(str2 + i + 1) == '\0',也就是寻找成功,返回移动后的主串。

最终通过主程序输出了world。

注解2

下面的例子,我们测试一个找不到的情况:

int main()
{
	system("color 0A");
	try
	{
		char a[] = "hello world";
		char b[] = "world";
		char d[] = "print";
		char* results = locatesubstr(a, d);
		while (*results != '\0')
			cout << *(results++);
	}
	catch (const char*ss)
	{
		cout << ss << endl;
	}
	return 0;
}

运行结果为:

发现str1一直在比较并向后移动,最终返回NULL值。

注解3

再换一个:

int main()
{
	system("color 0A");
	try
	{
		char a[] = "hello world";
		char b[] = "world";
		char d[] = "print";
		char e[] = "word";
		char* results = locatesubstr(a, e);
		while (*results != '\0')
			cout << *(results++);
	}
	catch (const char*ss)
	{
		cout << ss << endl;
	}
	return 0;
}

 

发现如我们所想,主串先向后移动6次,

然后word前三个字符相同,进入for循环,i自加3次,

发现第四个字符不同,主串继续向后移动strlen(world)这么多次,

最终返回NULL值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/566959.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql基础 — DDL、DML、DQL、DCL、函数、约束

文章目录 Mysql基础一、数据模型1.1 关系型数据库与非关系型数据库1.2 Mysql 数据模型 二、SQL2.1 SQL 通用语法2.2 SQL分类2.3 DDL2.3.1 数据库操作2.3.2 表操作 — 创建 & 查询2.3.3 表操作— 修改&删除2.3.4 数据类型2.3.4.1 数值类型2.3.4.2 字符串类型2.3.4.3 日期…

LabImg安装与使用

一、LabImg安装 安装命令语句 pip install labelimg 或 conda install labelimg 后者&#xff0c;可以有效避免依赖库缺失情况。一般&#xff0c;第一个命令语句无法安装时&#xff0c;可以尝试用第二个命令语句。 示例 以管理员身份打开命令提示符窗口&#xff0c;输入…

js的堆栈和垃圾回收机制(gc)

js的堆栈和垃圾回收机制&#xff08;gc&#xff09; 本文目录 js的堆栈和垃圾回收机制&#xff08;gc&#xff09;堆栈深拷贝和浅拷贝实现深拷贝 垃圾回收机制栈溢出概念垃圾产生算法策略V8引擎的优化新生代&#xff1a;Scavenge 算法老生代&#xff1a;标记-清除-整理 算法 堆…

厚积薄发丨美格智能子公司众格智能荣获“张江之星”“闵行区企业技术中心”双项企业授牌

5月23日下午&#xff0c;2023年闵行科技节开幕式在大零号湾科创大厦举行。在开幕式“创蝶变智造”板块&#xff0c;美格智能技术股份有限公司全资子公司众格智能科技&#xff08;上海&#xff09;有限公司&#xff08;以下简称&#xff1a;众格智能&#xff09;入选“张江之星”…

加速数实融合,数据交易3.0模式上新

数据交易市场将迎来真正的突破&#xff1f; 目前看的确如此。随着去年底“数据二十条”的颁布&#xff0c;业界普遍认为数据基础制度将加速走向落地与完善&#xff0c;数据要素化今年有望迎来全面提速&#xff0c;将极大促进数据交易市场走向规模化。 IDC预测&#xff0c;到2…

QMI8658 - 姿态传感器学习笔记 - Ⅲ

文章目录 1.复位1.1 上电复位&#xff1a;1.2 推荐工作条件 2. 校准(COD)2.1 校准步骤2.2 校准注意事项&#xff1a;2.3 校准状态指示2.4 校准参数更新 3. 自检3.1 加速度计自检3.2 陀螺仪自检 4. Ctrl94.1 写Ctrl94.2 读Ctrl94.3 Ctrl9详细命令说明 5. 中断5.1 同步采样模式5.…

直接缓存访问DCA

直接缓存访问DCA&#xff1a;网卡原本DMA写是将接收到的数据帧写入系统内存&#xff0c;DCA机制是网卡DMA写输入的数据能直接发送到属于CPU内部的L2高速缓存中&#xff0c;从而提高网络IO的性能。 设备驱动程序要初始化网卡的DCA功能&#xff0c;将CPU ID号&#xff08;通过获取…

CentOS安装Whisper | RedHat安装Whisper | 服务器上安装Whisper

1、升级Python版本&#xff08;可选&#xff09; CentOS 7.9 系统默认安装的Python版本有两个&#xff0c;如果输入python -V我们看到的是python2的版本信息&#xff0c;如果我们输入python3 -V我们看到的是python3的版本信息。 由于whisper要求使用的是python版本是在3.8到3…

Linux(Ubuntu)安装和使用Edge浏览器

全文内容完全由AI创作&#xff0c;并通过人工核验&#xff0c;感谢各位的阅读。 Microsoft Edge是一款现代化的浏览器&#xff0c;它拥有众多功能和强大的性能&#xff0c;为用户带来更加流畅的浏览体验。 Edge最近推出了分屏功能&#xff0c;支持一个窗口同时显示两个选项卡&…

MySQL基础 — 多表查询以及事务管理

文章目录 MySQL基础 — 多表查询以及事务管理一、多表查询1.1 对应关系1.2 准备数据1.3 概述1.4 内连接1.5 外连接1.6 自连接1.7 联合查询 union1.8 子查询1.8.1 标量子查询1.8.2 列子查询1.8.3 行子查询1.8.4 表子查询 二、事务2.1 简介2.2 操作演示2.3 控制事务2.3.1 控制事务…

深入浅出Vite:深入理解 Rollup 的插件机制

上一节我们学会了 Rollup 构建工具的使用&#xff0c;相信你已经对 Rollup 的基础概念和使用有了基本的掌握。同时我们也知道&#xff0c;仅仅使用 Rollup 内置的打包能力很难满足项目日益复杂的构建需求。对于一个真实的项目构建场景来说&#xff0c;我们还需要考虑到模块打包…

如何通过CRM系统做好客户的分级分类

随着市场竞争的不断加剧&#xff0c;尤其是以客户为中心时代的到来&#xff0c;企业越来越注重客户的管理和服务。而CRM系统&#xff0c;作为企业客户管理的重要工具&#xff0c;其核心任务是对客户进行分级分类&#xff0c;以便更好地为客户提供定制化的服务。 客户之间的价值…

在 Docker 容器中安装 nvm

目录 前言一、步骤1.下载nvm安装脚本2.激活nvm3.安装Node.js4.验证 Node.js 是否安装成功5.如果需要安装特定版本的 Node.js&#xff0c;可以使用以下命令6.如果需要使用特定版本的 Node.js&#xff0c;可以使用以下命令6.验证特定版本的 Node.js 是否安装成功 总结 前言 提示…

关于 arduino 中的 random()和randomSeed()的使用

0、random() 函数&#xff1a; 用于生成一个指定范围内的伪随机整数&#xff0c;可以使用该函数在程序中产生不同的随机数。其语法如下&#xff1a; random(min, max) 其中&#xff0c;min 表示随机数的最小值&#xff0c;max 表示随机数的最大值&#xff08;不包括该…

介绍几种常见的运维发布策略

随着Devops的发展&#xff0c;为了提高运维发布的成功率&#xff0c;探索出了多种发布策略。本文简单介绍几种常见发布策略, 以及它们适用的场景和优缺点。 第一种&#xff0c;停机发布 这是最早的一种发布策略&#xff0c;停机发布会在发布以前关闭服务&#xff0c;停止用户…

benders分解算法 逻辑思路整理(加星)

Benders decomposition 目录 1.benders的分类 2. 经典的benders分解 2.1 经典的benders分解注意点 2.2 benders分解的核心——子问题和对偶子问题的分析 benders分解本质是&#xff1a; &#xff08;1&#xff09;将问题分解为松弛主问题和子问题 &#xff08;2&#xff0…

支付宝SDK接口调试- cpolar内网穿透工具实现公网地址调试(1)

文章目录 1.测试环境2.本地配置3. 内网穿透3.1 下载安装cpolar内网穿透3.2 创建隧道 4. 测试公网访问5. 配置固定二级子域名5.1 保留一个二级子域名5.2 配置二级子域名 6. 使用固定二级子域名进行访问 转发自cpolar内网穿透的文章&#xff1a;Java支付宝沙箱环境支付&#xff0…

Cisco Identity Services Engine (ISE) 3.2 Patch2 发布 - 思科身份服务引擎

Cisco Identity Services Engine (ISE) 3.2 Patch2 发布 - 思科身份服务引擎 请访问原文链接&#xff1a;https://sysin.org/blog/cisco-ise-3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 工作场所零信任安全的核心所在 …

FL Studio水果软件好用吗?对电脑硬件环境有哪些需求

如果你打算将来朝着艺术和音乐方向发展&#xff0c;那么学习音乐理论和音乐制作就是一门基础课了。 实践才是检验学习效果途径&#xff0c;在我们日常的练习中&#xff0c;一款功能强大且易学的音乐制作工具是少不了的。在没有实际体验过各个音乐制作工具的功能前&#xff0c;…

SpringCloud概论

目录 1.实现微服务需要解决的问题 2.解决这些问题需要的技术栈 3.spring cloud 4.Netflix和Alibaba 5.springCloud和doubbo 6.版本适配 7.停更 1.实现微服务需要解决的问题 马丁福勒于2014年在一篇文章中提出微服务架构&#xff0c;原文地址如下&#xff1a; Microser…