实验三 串
一、实验目的及要求
1.实验目的
1)掌握串的概念、抽象数据类型和特点,掌握串的顺序存储结构的存储思想及其程序实现,掌握串的各种基本操作。
2.实验要求
1)用结构体类型描述串的存储结构,对可能出现的问题预先分析,确定调试步骤和测试方法,编写源程序,尽可能考虑算法的健壮性,对实验中出现的问题进行分析、总结,完成实验报告。
2)上机过程中要遵守实验室的各项规章制度,爱护实验设备,保持环境卫生。
3)本课程的实验过程中,不得进行游戏、上网等操作。
二、实验环境(工具、配置等)
1.硬件要求:计算机一台。
2.软件要求:Windows11操作系统,使用C++语言,编译环境Dev-C++。
3.数据结构与算法分析书一本,采用C++11标准。
三、实验内容(实验方案、实验步骤、设计思路等)
1. 实验方案:
- 根据课本和老师课堂中讲解的内容,编写具体函数实现子串位置的定位函数,例如编写串的判等、求串长、求子串等操作函数实现,完成实验报告。
2.实验步骤:
-
1)先编写具体代码实现串的顺序存储。
-
2)进行求取KMP算法中next数组和nextval数组代码的编写
-
3)编写实现求取子串的函数。
-
4)进行串的判等的函数和求串长函数的编写。
3.设计思路:
-
先实现串的顺序存储,然后编写具体函数,最后书写主函数中调用函数,检查结果是否正确。
四、实验结果与分析
实验结果
1.实现串的顺序存储,然后实现KMP算法中子串的定位函数,效果如图4-1:
图4-1 链栈输出结果
2.使用编译软件编写具体函数,实现具体功能,并检验程序是否编译运行成功,如图4-2:
图4-2 程序输出结果
实验分析:
1.实验遇到的问题:
1)编写的串的顺序存储,在初始化时其下标从0开始,而匹配时下标从1开始,不知如何转换。
2)在编写KMP匹配算法时,next数组的传参出现问题。
3)编写截取子串函数时,出现输出的子串大于想要求取的子串长度。
2.问题解决的方法:
1)针对遇到的问题1,在输入时直接让其从下标为1开始输入,如cin>>(s.th)+1;。
2)针对遇到的问题2,将next数组设计为全局变量即可。
3)针对遇到的问题3,检查函数体时,发现是截取的子串的初始长度未设置为0,更改后程序正常运行。
五、源程序
#include<iostream>
using namespace std;
#define MAX_SIZE 100 //串的最大长度
typedef struct {
char ch[MAX_SIZE+1]; //存储串的一维数组
int S_length; //串的长度
}Str_ing;
int Next[MAX_SIZE]; //定义next数组
int nextval[MAX_SIZE]; //定义nextval数组
//求取字符串的长度
int Str_length(Str_ing T){
int i=1;
while(T.ch[i]!='\0'){
i++;
}
return i-1; //输入直接从下标为1输入,所以减1
}
//两个字符串判等
void Str_cmp(Str_ing S,Str_ing T){
bool flag=true;
if(S.S_length!=T.S_length){
cout<<"两个字符串不相等!"<<'\n';
return ;
}
else{
for(int i=1;i<=S.S_length;i++){
if(S.ch[i]!=T.ch[i]){
flag=false;
break;
}
}
if(flag){
cout<<"两个字符串相等!"<<'\n';
}
else{
cout<<"两个字符串不相等!"<<'\n';
}
}
}
//截取字符串
void Str_sub(Str_ing S,int pos,int len){
int i=0;
Str_ing sub;
sub.S_length=0;
for(int i=0;i<len;i++){
sub.ch[i]=S.ch[pos];
pos++;
sub.S_length++;
}
cout<<"截取后的子串为:";
for(int i=0;i<sub.S_length;i++){
cout<<sub.ch[i];
}
}
//串的匹配
int KMP_string(Str_ing S,Str_ing T,int x){
int i=x,j=1;
int m=S.S_length,n=T.S_length;
while(i<=m&&j<=n){
if(j==0||S.ch[i]==T.ch[j]){
++i;
++j;
}
else{
j=nextval[j];
}
}
if(j>T.S_length){
return i-T.S_length;
}
else{
return 0;
}
}
//获取next数组
void Get_Next(Str_ing T,int next[]){
int i=1;
next[1]=0;
int j=0;
int m=T.S_length;
while(i<m){
if(j==0||T.ch[i]==T.ch[j]){
++i;
++j;
next[i]=j;
}
else{
j=next[j];
}
}
}
//获取nextval数组
void Get_nextval(Str_ing T,int nextval[]){
int i=1;
int j=0;
nextval[1]=0;
while(i<T.S_length){
if(j==0||T.ch[i]==T.ch[j]){
++i;
++j;
if(T.ch[i]!=T.ch[j]){
nextval[i]=j;
}
else{
nextval[i]=nextval[j];
}
}
else{
j=nextval[j];
}
}
}
int main(){
Str_ing S,T;
cout<<"请输入主串长度:";
cin>>S.S_length;
cout<<"请输入主串:";
cin>>(S.ch)+1;
cout<<"请输入匹子串长度:";
cin>>T.S_length;
cout<<"请输入子串:";
cin>>(T.ch)+1;
Get_Next(T,Next);
Get_nextval(T,nextval);
int x=KMP_string (S,T,1);
cout<<"子串的定位为:"<<x<<'\n';
cout<<"串的判等"<<"\n";
Str_ing a,b,que,c;
cout<<"请输入串1的长度和串:";
cin>>a.S_length>>(a.ch)+1;
cout<<"请输入串2的长度和串:";
cin>>b.S_length>>(b.ch)+1;
Str_cmp(a,b);
cout<<"请输入你想要的查询的串的长度和串:";
cin>>que.S_length>>(que.ch)+1;
cout<<"请输入你想要求的子串首位置和子串长度:";
int pos,len;
cin>>pos>>len;
Str_sub(que,pos,len);
cout<<'\n';
cout<<"请输入需要求取长度的字符串:";
cin>>(c.ch)+1;
int len2=Str_length(c);
cout<<"字符串的长度为:"<<len2;
return 0;
}