【数据结构】实验七:字符串

实验七 字符串实验报告

一、实验目的与要求

1)巩固对串的理解;

2)掌握串的基本操作实现;

3)掌握 BF 和 KMP 算法思想。

二、实验内容

1. 给定一个字符串ababcabcdabcde和一个子串abcd,查找字串是否在主串中出现。出现就返回主串中的第一个匹配下标,没有则返回-1。本题采用BF串匹配算法。

2.编写一个函数,计算一个子串在一个主串中出现的次数,如果该子串不出现,则返回0。本题考虑子串重叠,如:子串为aa,主串为aaa,考虑子串重叠结果为2,不考虑子串重叠结果为1。

示列1:输入:"ababab","abababab"    返回值:2

示列2:输入:"abab","abacabab"  返回值:1

提示:

首先进行特殊情况判断,如果模式串长度大于主串,或者主串为空,返回0。

然后分别遍历主串和模式串,只要当前字符相等,模式串和主串均后移一位,如果不相等,模式串重新回退到索引0的位置。

当模式串索引达到长度m时,说明全部匹配上了。此时将匹配次数加一,同时主串索引i回退到上次匹配开头的下一位,模式串索引j回到0。

采用kmp算法

三、实验结果

1)请将调试通过的运行结果截图粘贴在下面,并说明测试用例和运行过程,简述算法思想。

2)请将源代码cpp文件和实验报告一起压缩上传。


实验1


运行结果:

 

 

算法思想:

BF算法的思想主要如下:在主串和子串中设置比较的下标i和j(本段代码中初始化均为0)。循环比较直到主串中所剩字符个数小于子串的长度,或者是子串的所有字符均比较完。如果主串A和子串B满足A[i]=B[i],那么继续比较子串和主串的下一个字符;否则,将i和j回溯,准备下一趟的比较。如果子串中的所有字符均比较完,那么说明匹配成功,返回匹配的起始比较下标;否则,说明匹配失败,按照题目要求返回-1。

实验代码:

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;



//BF串匹配算法

int bf(char *strA, char *strB){

   //strA是主串,strB是子串

    int i=0,j=0;

    int lena=strlen(strA);//主串的长度

    int lenb=strlen(strB);//子串的长度

    while(i<lena && j<lenb){

        if(strA[i]==strB[j]){

            i++;

            j++;

        }

      else{

            i=i-j+1;//如果i、j初始值为1,则返回i=i-j+2?

            j=0;//重置子串的标记位置j

        }

    }//跳出循环,遍历完成

   

    //判断字串情况

    if(j==lenb){

        return i-j+1;//成功匹配

    }

    return -1;//不成功匹配

}



//主函数->调试

int main() {

    //int mybf=bf("ababcabcdabcde","abcd");

    char strA[1000],strB[1000];//max长度设置为1000

    cout<<"请输入主串:"<<endl;

   cin>>strA;

   cout<<"请输入子串:"<<endl;

   cin>>strB;

   int mybf=bf(strA,strB);

   if(mybf>0){

      cout<<"主串中的第一个匹配下标:"<<mybf<<endl;

   }

    else{

      cout<<mybf<<endl;

   }

    return 0;

}

 

实验2

运行结果:

 

 

算法思想:

KMP算法的思想主要如下:在主串A和子串B中设置比较的下标i和j(本段代码中初始化均为0)。循环比较直到主串中所剩字符个数小于子串的长度,或者是子串的所有字符均比较完。如果A[i]=B[j]或j=0,那么继续比较A和B的下一个字符;否则,将j向右滑动到next[i]的位置(j= next[i]),准备下一趟的比较。如果子串中的所有字符均比较完,那么说明匹配成功,返回匹配的起始比较下标;否则,说明匹配失败,按照题目的要求返回0。

实验代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

int next[100];//全局数组变量 

//获取next数组 
void getNext(char b[],int next[]){
	int len=strlen(b);
	next[0]=-1;
	int k=-1;
	int j=0;
	while(j<len){
		if(k==-1 || b[k]==b[j]){
			j++;
			k++;
			next[j] = k;
		}
		else{
			k=next[k];
		}
	}
}

//KMP算法  
int kmp(char *a,char *b){
	int lena=strlen(a);
	int lenb=strlen(b);
	int i=0,n=0,k=0;//n作为计数器 
	while(i<lena){
		if(k==-1 || a[i]==b[k]){
			++i;
			++k;
		}
		else{
			k=next[k];
		}
		if(k==lenb){
			n++;
			k=next[k];
		}
	}
	return n;
}

int main(){
	char a[100000],b[10000];//a为主串,b为子串 
	cout<<"请输入主串:"<<endl; 
	cin>>a;
	cout<<"请输入子串:"<<endl; 
	cin>>b;
	getNext(b,next);
	cout<<"子串出现次数为:"<<kmp(a,b);
	return 0; 
}

其他:

#include<iostream>
using namespace std;

struct String{
	char *elem;
	int length;
};

void Strcpy(String &S,const char str[]){
	//忌引用数组 ,const!!!
	int i=0;
	int str_len=0;
	while(str[i]!='\0'){
		str_len++;
		i++;
	}//字符串长度 
	if(!str_len) 
	    S.length=0;
	int k=1,j=0;
	S.elem=new char[str_len+1];
	while(k<=str_len)
	S.elem[k++]=str[j++];
	S.elem[0]=' ';//0号位随意 
	S.length=str_len;
}

int StrIndex_BF(String &S,String &T,int pos){
	int i=pos,j=1;
	while((i<=S.length)&&(j<=T.length)){
		//while((i<=S.length-T.length+1)&&(j<=T.length))错误!! 
		if(S.elem[i]==T.elem[j]){
			i++;j++;
		}
		else{
			i=i-j+2;//回溯操作 
			j=1;
			if(i>S.length-T.length+1)
			break;//S中剩下元素小于T的元素个数 
		}
	}
	if(j>T.length)//T中全部字符均匹配成功! 
	return (i-T.length);
	else
	return -1;
}

void Destroy(String &S){
	delete []S.elem;
}

int main(){
	String S,T; 
//	Strcpy(S,"ababcabcdabcde");//主串 
//	Strcpy(T,"abcd");//模式串
	Strcpy(S,"ababcabcacbab");//主串 
	Strcpy(T,"abcac");//模式串 
	int p=StrIndex_BF(S,T,1);
	//匹配函数 
	if(p!=-1)
	cout<<"匹配成功!主串中的第一个匹配下标为:"<<p<<endl;
	else
	cout<<"匹配失败!"<<endl;
	Destroy(S);
	Destroy(T);
    return 0;
}
#include<iostream>
using namespace std;

struct String{
	char* elem;
	int length;
};

void StrCopy(String &s,char a[]){
	int i=0;
	int strlen=0;
	while(a[i]!='\0'){
		strlen++;
		i++;
	}
	s.elem=new char[strlen+1];
	int k=1,j=0;
	while(j<strlen)
	s.elem[k++]=a[j++];
	s.elem[0]='\0';
	s.length=strlen;
}

void Get_next(String &T,int (&next)[20]){
	int i=0,j=1;
	next[1]=0;
	while(j<T.length){
		if(i==0||T.elem[i]==T.elem[j]){
	    	i++;j++;next[j]=i;
     	}
    	else
        	i=next[i];
	}
}

int Strmatch_KMP(String &S,String &T,int next[]){
	int i=1,j=1,num=0;
	if(S.length<T.length)
	return 0;
	while((i<=S.length)&&(j<=T.length)){
		//while((i<=S.length-T.length+1)&&(j<=T.length))错误!! 
		if(j==0||(S.elem[i]==T.elem[j])){
			i++;j++;
		}
		else  j=next[j];
		if(j>T.length){
			num++;i=i-j+2;j=1;//回溯
			if(i>S.length-T.length+1)
			break;//S中剩下元素小于T的元素个数  
		}
	}
	return num;
}

void Destroy(String &S){
	delete []S.elem;
}

int main(){
	char a[20],b[20];
	gets(a);
	gets(b);
	String S,T;
	StrCopy(S,a);
	StrCopy(T,b);
	int next[20]={0,0,1};//初始化next【i】 
	Get_next(T,next);//找到对应的k值 
	int num=Strmatch_KMP(S,T,next);//重叠次数 
	if(!num) cout<<"子串不在主串中出现!"<<endl;
	else cout<<"子串在主串中出现,且重叠结果为:"<<num<<endl;
	Destroy(S);
	Destroy(T);
	return 0;
} 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Oracle 多条记录根据某个字段获取相邻两条数据间的间隔天数,小于31天的记录都筛选出来

需求描述&#xff1a;在Oracle中 住院记录记录表为v_hospitalRecords&#xff0c;表中FIHDATE入院时间&#xff0c;FBIHID是住院号&#xff0c; 我想查询出每个患者在他们的所有住院记录中是否在一个月内再次入院(相邻的两条记录进行比较)&#xff0c;并且住院记录大于一的患者…

【高分论文密码】大尺度空间模拟预测与数字制图教程

详情点击链接&#xff1a;【高分论文密码】大尺度空间模拟预测与数字制图 一&#xff0c;R语言空间数据及数据挖掘关键技术 1、R语言空间数据及应用特点 1)R语言基础与数据科学 2)R空间矢量数据 3)R栅格数据 2、R语言空间数据挖掘关键技术 二&#xff0c;R语言空间数据高…

ChatGPT有几个版本,哪个版本最强,如何选择适合自己的?

​ChatGPT就像内容生产界的瑞士军刀。它可以是数学导师、治疗师、职业顾问、编程助手&#xff0c;甚至是旅行指南。只要你知道如何让它做你想做的事&#xff0c;ChatGPT几乎可以提供你要的任何东西。 但重要的是&#xff0c;你知道哪个版本的ChatGPT最能满足你的需求吗&#x…

C++容器——list的模拟实现

目录 一.list的基本结构 二. 接下来就是对list类构造函数的设计了&#xff1a; 三.链表数据的增加&#xff1a; 四.接下来就是迭代器的创建了&#xff1a; 四.简单函数的实现&#xff1a; 五.构造与析构 六.拷贝构造和赋值重载 传统写法: 现代写法&#xff1a; 七.迭…

运维高级--shell脚本完成分库分表

为什么要进行分库分表 随着系统的运行&#xff0c;存储的数据量会越来越大&#xff0c;系统的访问的压力也会随之增大&#xff0c;如果一个库中的表数据超过了一定的数量&#xff0c;比如说MySQL中的表数据达到千万级别&#xff0c;就需要考虑进行分库分表&#xff1b; 其…

基于拉格朗日-遗传算法的最优分布式能源DG选址与定容(Matlab代码实现)

目录 1 概述 2 数学模型 2.1 问题表述 2.2 DG的最佳位置和容量&#xff08;解析法&#xff09; 2.3 使用 GA 进行最佳功率因数确定和 DG 分配 3 仿真结果与讨论 3.1 33 节点测试配电系统的仿真 3.2 69 节点测试配电系统仿真 4 结论 1 概述 为了使系统网损达到最低值&a…

Paragon NTFS2023最新版Mac读写NTFS磁盘工具

Paragon NTFS for Mac是Mac平台上一款非常优秀的读写工具&#xff0c;可以在Mac OS X中完全读写、修改、访问NTFS硬盘、U盘等外接设备的文件。这款软件最大的亮点简书可以让我们读写 NTFS 分区&#xff0c;因为在Mac OS X 系统上&#xff0c;默认状态下我们只能读取NTFS 分区&a…

【Ubuntu18.04免密码登录SSH】

Ubuntu18.04免密码登录SSH 1 查看Ubuntu18.04系统中是否存在SSH服务2 配置SSH2.1 先删除一下ssh的目录&#xff0c;重新配置2.2 生存公钥和私钥2.3 将公钥上传到需要登录的服务器2.4 测试登录 1 查看Ubuntu18.04系统中是否存在SSH服务 sudo ps -e |grep ssh没有的话&#xff0…

网络安全(黑客)自学基础到高阶路线

01 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面…

[JavaWeb]MySQL的安装与介绍

MySQL的安装与介绍 一.数据库相关概念1.1 数据库1.2 常见的关系型数据库管理系统 二.MySQL数据库1.MySQL的安装2.配置环境变量3.新建MySQL配置文件4.初始化MySQL5.注册MySQL的服务6.修改默认账户与密码7.连接MySQL服务8.MySQL的卸载 三.MySQL的数据模型1.关系型数据库 一.数据库…

Gitlab 备份与恢复

备份 1、备份数据&#xff08;手动备份&#xff09; gitlab-rake gitlab:backup:create2、备份数据&#xff08;定时任务备份&#xff09; [rootlocalhost ]# crontab -l 00 1 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create 说明&#xff1a;每天凌晨1点备份数据…

C++之lambda表达式/function/using/typedef用法总结(一百六十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

软件设计师学习第一章

计算机组成与体系结构&#xff08;6分&#xff09; 内容概述 数据的表示 进制转换 R 进制转十进制使用按权展开法&#xff0c;其具体操作方式为&#xff1a;将 R 进制数的每一位数值用 Rk 形示&#xff0c;即幂的底数是 R &#xff0c;指数为 k &#xff0c; k 与该位和小数点…

惠普HP Color Laser 150a开机红色感叹号闪烁不打印故障解决方法

故障描述&#xff1a; 惠普HP Color Laser 150a开机红色感叹号闪烁&#xff0c;不能打印&#xff0c;电脑提示C3-6140。 检测分析&#xff1a; 在解决C3-6140错误代码之前&#xff0c;我们需要先检查打印机是否连接正常。如果打印机连接不正常&#xff0c;也可能会出现这个错误…

2、HAproxy调度算法

HAProxy的调度算法可以大致分为以下几大类&#xff1a; 静态算法&#xff1a;这类算法的调度策略在配置时就已经确定&#xff0c;并且不会随着负载的变化而改变。常见的静态算法有&#xff1a; Round Robin(轮询) Least Connections(最少连接数) Static-Weight(静态权重) Sourc…

总结 Android 开发中截取字符串的方法

string str”hello word”;int i5; 1 取字符串的前i个字符 strstr.Substring(0,i); // or strstr.Remove(i,str.Length-i);substring(start,end)&#xff1a;substring是截取2个位置之间及start-end之间的字符串2 去掉字符串的前i个字符&#xff1a; strstr.Remove(0,i); // or…

LabVIEW开发谐振器陀螺仪仿真系统

LabVIEW开发谐振器陀螺仪仿真系统 陀螺仪是INS系统中最重要的传感器。它们的性能&#xff08;如精度和偏置稳定性&#xff09;决定了INS系统的水平。陀螺仪按原理分为三类&#xff1a;角动量守恒、萨格纳克效应和科里奥利效应。旋转坐标系中的移动物体受到的力与旋转坐标系的角…

flutter:角标

角标应该非常常见了&#xff0c;以小说app为例&#xff0c;通常会在小说封面的右上角上显示当前未读的章数。 badges 简介 Flutter的badges库是一个用于创建徽章组件的开源库。它提供了简单易用的API&#xff0c;使开发者可以轻松地在Flutter应用程序中添加徽章效果。 官方文…

chatGPT 学习分享:内含PPT分享下载

InstructGPT论文地址&#xff1a; Training language models to follow instructions with human feedbackchatGPT地址&#xff1a;openAI个人整理的PPT&#xff08;可编辑&#xff09;&#xff0c;下载地址&#xff1a;chatGPT学习分享PPT

windows环境下,安装elasticsearch

jdk ElasticSearch是基于lucence开发的&#xff0c;也就是运行需要java jdk支持。 我下载了 elasticsearch-8.9.0-windows-x86_64.zip&#xff0c;带了OpenJDK。 ElasticSearch下载 https://www.elastic.co/downloads/elasticsearch 安装ElasticSearch 下载安装包后解压 修…