【算法设计与分析】实验1:字符串匹配问题的算法设计与求解

news/2025/1/31 0:14:13 标签: 算法, 数据结构, 贪心算法, 开发语言, 笔记

目录

一、实验目的

二、实验环境

三、实验内容 

四、核心代码

五、记录与处理

六、思考与总结

七、完整报告和成果文件提取链接


一、实验目的

        给定一个文本,在该文本中查找并定位任意给定字符串。

        1、深刻理解并掌握蛮力法设计思想

        2、提高应用蛮力法设计算法的技能;

        3、理解观点:用蛮力法设计算法策略,一般来说,经过适度的努力后,都可以对算法的第一个版本进行一定程度的改良,改进其时间性能。

二、实验环境

        1、机房电脑  Window7

        2、Eclipse/DEVC++等

三、实验内容 

1、针对给定两组字符串,分别利用BF算法及KMP算法开展问题分析、建模、算法设计与优化;

(1)问题分析:

当给出两组字符串,主串s,子串t,要想找到子串t在主串s中的位置,常规时我们用肉眼可以一眼看出,但当字符串非常多时,问题就变得复杂了,用代码思想解决问题时,我们最容易想到暴力匹配BF算法

为了避免BF算法多次回溯的缺点,我们要尽量减少回溯的次数。

KMP算法则提出了采用相等前后缀来解决BF算法多次回溯的缺点。比如:

根据KMP算法的思想,两个字符串拥有相同部分的前后缀,所以只用移动一部分就可以了

求出其最长相等前后缀是关键,根据此数组存储数值——表示该处字符不匹配时应该回溯到的字符下标

求出子串的next数组

在下面情况时,a与c不匹配:

将子串的指针移动到下标为2的字符下。

假设主串长度为m,子串长度为n ,KMP算法的时间复杂度为O(m+n),BF算法的空间复杂度为O(n),与BF算法相比,算法效率提高了很多。

(2)算法改进

而对于KMP算法,还有需要改进的地方,根据nextval的值,我们很容易就知道回溯后的字符与原字符是否相同,这样就减少了原KMP算法中,部分重复回溯的过程。

对上述算法进行时间复杂性分析,并输出程序运行时间及运行结果。

最好情况下,时间复杂度为O(n);全部遍历完时的最差时间复杂度为O(m*n),算法空间复杂度为O(1),BF算法耗时间不耗费空间。KMP算法的时间复杂度为O(m+n),空间复杂度为O(n),与BF算法相比,算法效率提高了很多。

四、核心代码

int BF(SqString s,SqString t)            //BF算法 
{
	int i=0,j=0;
	while(i<s.length&&j<t.length)		
	{
		if(s.data[i]==t.data[j])		
		{
			i++;						
			j++;
		}
		else
		{
			i=i-j+1;					
			j=0;						
		}
	}
	if(j>=t.length) 					
	    return(i-t.length);		
	else
	    return(-1);
}

void GetNext(SqString t,int next[])    //求子串t的next数组,进行代码优化
{
	int j,k;							
	j=0;k=-1;
	next[0]=-1;							
	while(j<t.length-1)					
	{									
		if(k==-1||t.data[j]==t.data[k])		
		{
			j++;k++;
			next[j]=k;						
		}
		else k=next[k];						
	}										
}

int KMPIndex(SqString s,SqString t)       //KMP算法
{
	int next[MaxSize],i=0,j=0;
	GetNext(t,next);
	while(i<s.length&&j<t.length)
	{
		if(j==-1||s.data[i]==t.data[j])   
		{								  
			i++;
			j++;
		}
		else j=next[j];
	}
	if(j>=t.length)
	    return(i-t.length);
	else
	    return(-1);
}

void GetNextval(SqString t,int nextval[])  //求模式串t的nextval数组,进行KMP的代码优化
{
	int j=0,k=-1;							
	nextval[0]=-1;							
	while(j<t.length-1)
	{
		if(k==-1||t.data[j]==t.data[k])		
		{									
			j++;k++;						
			if(t.data[j]!=t.data[k])		
			   nextval[j]=k;
			else
			   nextval[j]=nextval[k];		
		}
		else k=nextval[k];
	}
}

五、记录与处理

实验数据及结果分析。实验时输入多组测试数据,以及对应的算法运行结果截图、算法运行时间

六、思考与总结

对于字符串匹配问题两种算法以及改进的对比:

1.BF算法,暴力匹配法,即逐个字符进行比对,遍历主串,从每个字符开始与子串进行比较。若字符不匹配,主串回溯到下一个字符,子串回到起始位置。时间复杂度:最好情况为O(n),最坏情况为O(m*n);空间复杂度为O(1)。

缺点:效率极低。

2.KMP算法利用了相等前后缀避免多次回溯,使用next数组记录子串的最长相等前后缀,计算子串的next数组,遍历主串和子串,不匹配时,子串根据next数组进行回溯。时间复杂度为O(m+n),空间复杂度为O(n)。

缺点:在某些情况下,如重复字符较多,会有冗余回溯。

七、完整报告和成果文件提取链接

完整可运行代码以及相关实验报告以下链接可获取:
链接: https://pan.baidu.com/s/1iss6-C2nxZQGkEpo-WDn0A?pwd=g5cg 提取码: g5cg 
 


http://www.niftyadmin.cn/n/5838174.html

相关文章

2024年除夕

多少年前的除夕&#xff0c;一如今天这样的除夕&#xff1b;多少年后的除夕&#xff0c;也一如多少年前的除夕。 无数个这样的除夕下午&#xff0c;我打开电脑&#xff0c;望着窗外安静的小区&#xff0c;车声渐渐稀疏的马路&#xff0c;想写下一些新的感受时&#xff0c;多少…

IPhone13 Pro Max设备详情

目录 产品宣传图内部图——后设备详细信息 产品宣传图 内部图——后 设备详细信息 信息收集于HubWeb.cn

ThinkPad E480安装Ubuntu 18.04无线网卡驱动

个人博客地址&#xff1a;ThinkPad E480安装Ubuntu 18.04无线网卡驱动 | 一张假钞的真实世界 遗憾的是虽然下面的方法可以解决&#xff0c;但是内核升级后需要重新安装。 基本信息 Ubuntu 18.04ThinkPad E480使用下面的命令查看 Linux 内核&#xff1a; $ uname -r 5.0.0-3…

Node.js 中文编码问题全解析

Node.js 中文编码问题全解析 问题背景 在 Node.js 中执行 Gradle 命令时遇到中文输出乱码问题。这个问题涉及 Windows 系统、Java 进程和 Node.js 三个层面的编码处理。 问题分析 最初的错误代码 gradleProcess.stdout.setEncoding(utf-8); // 错误&#xff1a;假设输出是…

openeuler 22.03 lts sp4 使用 cri-o 和 静态 pod 的方式部署 k8s-v1.32.0 高可用集群

前情提要 整篇文章会非常的长…可以选择性阅读,另外,这篇文章是自己学习使用的,用于生产,还请三思和斟酌 静态 pod 的部署方式和二进制部署的方式是差不多的,区别在于 master 组件的管理方式是 kubectl 还是 systemctl有 kubeadm 工具,为什么还要用静态 pod 的方式部署?…

CISCO路由基础全集

第一章&#xff1a;交换机的工作原理和基本技能_交换机有操作系统吗-CSDN博客文章浏览阅读1.1k次&#xff0c;点赞24次&#xff0c;收藏24次。交换机可看成是一台特殊的计算机&#xff0c;同样有CPU、存储介质和操作系统&#xff0c;只是与计算机的稍有不同。作为数据交换设备&…

buu-warmup_csaw_2016-好久不见27

简单的栈溢出提&#xff0c;和上一题不一样的点是&#xff0c;后面函数&#xff0c;上一个是bin\sh,这一个是cat flag.txt,找后面函数地址即可

基于Ubuntu交叉编译ZLMediaKit

一、确保基于虚拟机VMVare的Ubuntu能正常上网 1、设置WIFI硬件无线网卡上网 菜单栏的“编辑”->选择“虚拟网络编辑器”&#xff0c;在弹出的窗口中&#xff0c;点击桥接模式的VMnet0&#xff0c;然后在下方选择“桥接模式”&#xff0c;网卡下拉栏&#xff0c;选择你目前…