串的基本操作和模式匹配(严蔚敏版数据结构)

该代码实现了串的顺序存储结构,包括赋值、复制、判断串空、比较、统计串长、清空、拼接和返回子串等基本操作。此外,还包含了BF暴力匹配和KMP模式匹配算法,用于字符串的定位。程序提供了一个简单的交互式菜单供用户选择执行不同的操作。
//串的基本操作:赋值,复制,串空判断,比较,统计串长,清空串,拼接串,返回子串 
//插入和删除以及定位和模式匹配(BF算法,KMP算法)
//2023年4月11日08:29:12 author:夜航星 
#include<iostream>
#include<iomanip>
#define MaxLen 255
using namespace std;
//串的顺序存储结构 
//考虑到存储效率和算法方便性,使用顺序存储结构 
typedef struct{
	char ch[MaxLen+1];
	int length;
}SString; 

////串的堆式存储结构
//typedef struct{
//	char *ch;
//	int length;
//}HString;

////串的链式存储结构 
//#define ChunkSize 80
//typedef struct Chunk{
//	char ch[ChunkSize];
//	struct Chunk *next;
//}Chunk;
//typedef struct{
//	Chunk *head,*tail;
//	int length;
//}LString;

//赋值
//函数参数可以用SString,也可以用char数组。早上写的时候是用char数组写的
//下午写的时候发现用SString和教材更加对应,所以推荐自己动手写一下SString
//的代码。后文的插入删除都是用SString实现,前面则使用char数组。但无论是
//哪个方式,思想都是一样的,只不过一个下标从1开始,一个下标从0开始。
void StrAssign(SString &S,char s[])
{
	int i=0;
	S.length = 0;
	while(s[i]!='\0')
	{
		S.ch[i+1] = s[i];
		i++;
		S.length++;
	}
	S.ch[i+1] = '\0';
} 

//复制
void StrCopy(SString &S,char s[]) 
{
	int i=0;
	S.length = 0;
	while(s[i]!='\0')
	{
		S.ch[i+1] = s[i];
		i++;
		S.length++;
	}
	S.ch[i+1] = '\0';
}

//判断串空
void StrEmpty(SString S)
{
	if(S.length==0)
	{
		cout<<"空串!"<<endl;
	}else
	{
		cout<<"非空串!"<<endl;
	}
} 

//串的比较
void StrCompare(SString S,char s[])
{
	int i=0;
	int flag=0;
	while(s[i]!='\0'&&S.ch[i+1]!='\0')
	{
		if(S.ch[i+1]!=s[i])
		{
			cout<<S.ch[i+1]-s[i]<<endl;
			flag=1;
			break;
		}else
		{
			i++;
		}	
	}
	if(s[i]=='\0'&&S.ch[i+1]=='\0')
	{
		cout<<"0"<<endl;
	}else if(flag==0)
	{
		if(s[i]=='\0')
		{
			cout<<"S>s"<<endl;
		}else if(S.ch[i+1]=='\0')
		{
			cout<<"S<s"<<endl;
		}
	}	
} 

//串的长度
void StrLength(SString S)
{
	cout<<"串的长度为:"<<S.length<<endl;
} 

//清空串
void ClearString(SString &S)
{
	S.length = 0;
	S.ch[1] = '\0';
	cout<<"串已清空!"<<endl;
}

//串的拼接
void Concat(char t[],SString S,char s[])
{
	int i=1,j=0;
	int t_length = 0;
	while(S.ch[i]!='\0')
	{
		t[i-1] = S.ch[i];
		i++;
		t_length++;
	}
	i--;
	while(s[j]!='\0')
	{
		t[i] = s[j];
		i++;
		j++;
		t_length++;
	}
	t[i] = '\0';
	cout<<"拼接之后的串为:"<<t<<endl;
	cout<<"拼接后串的长度为:"<<t_length<<endl;
} 

//返回子串
void SubString(char Sub[],SString S,int pos,int len)
{
	if((pos>=1&&pos<=S.length)&&(len>=0&&len<=S.length-pos+1))
	{
		int i,j;
		for(i = pos,j = 0;i<=S.length&&j<len;i++,j++)
		{
			Sub[j] = S.ch[i];
		}
		Sub[j] = '\0';
		cout<<"子串的内容为:"<<Sub<<endl;
	}
	else
	{
		cout<<"输入不合法,请输入合理的位置和长度"<<endl;
	}
} 

//BF算法即暴力匹配算法 
void Index_BF(SString S,SString T,int pos)
{
	int i = pos,j=1;
	while(i<=S.length&&j<=T.length)
	{
		if(S.ch[i]==T.ch[j])
		{
			i++;
			j++;
		}else
		{
			i = i-j+2;
			j=1;
		}
	}
	if(j>T.length)
	{
		cout<<"匹配成功,对应位置为:"<<i - T.length<<endl;
	}else
	{
		cout<<"匹配失败!"<<endl;
	}
}

//求next数组(用于KMP算法)
void get_next(SString T,int next[])
{
	int i = 1;
	next[1] = 0;
	int j = 0;
	while(i<T.length)
	{
		if(j==0||T.ch[i]==T.ch[j])
		{
			i++;
			j++;
			next[i] = j;
		}else
		{
			j = next[j];
		}
	}
} 

//KMP算法 
void Index_KMP(SString S,SString T,int pos,int next[])
{
	int i = pos;
	int j = 1;
	while(i<=S.length && j<=T.length)
	{
		if(j==0||S.ch[i]==T.ch[j])
		{
			i++;
			j++;
		}else
		{
			j = next[j];
		}
	}
	if(j>T.length)
	{
		cout<<"匹配成功,对应位置为:"<<i-T.length<<endl;
	}else
	{
		cout<<"匹配失败!"<<endl;
	}
}


//定位
void Index(SString S,SString T,int pos,int next[])
{
	int sel;
	cout<<"请选择匹配算法:"<<endl;
	cout<<"1.BF算法"<<endl;
	cout<<"2.KMP算法"<<endl;
	cin>>sel;
	switch(sel)
	{
		case 1:
		{
			Index_BF(S,T,pos);
			break;
		}
		case 2:
		{
			Index_KMP(S,T,pos,next);
			break;
		}
	}
} 

//插入
//在主串S的第pos个字符前插入子串T 
void StrInsert(SString &S,int pos,SString T)
{
	int i,j,k;
	for(i=S.length+T.length;i>=pos;i--)
	{
		S.ch[i] = S.ch[i-T.length];
	}
	S.length = S.length+T.length;
	for(j = pos,k = 1;j<=pos+T.length;j++,k++)
	{
		if(T.ch[k]!='\0')
		{
			S.ch[j] = T.ch[k];
		}
	}
	cout<<"插入之后的主串为:";
	for(int i=1;i<=S.length;i++)
	{
		cout<<S.ch[i];
	}
	cout<<endl;
}

//删除 
void StrDelete(SString &S,int pos,int len)
{
	int i;
	for(i = pos;i<=S.length-pos;i++)
	{
		S.ch[i] = S.ch[i+len];
	}
	S.length = S.length-len;
	cout<<"删除之后的主串为:";
	for(int i=1;i<=S.length;i++)
	{
		cout<<S.ch[i];
	}
	cout<<endl;
}

//菜单 
void ShowMenu()
{
	cout<<"*********1.赋值*********"<<endl;
	cout<<"*********2.复制*********"<<endl;
	cout<<"*********3.判断串空*****"<<endl;
	cout<<"*********4.串的比较*****"<<endl;
	cout<<"*********5.串长*********"<<endl;
	cout<<"*********6.清空串*******"<<endl;
	cout<<"*********7.串的合并*****"<<endl;
	cout<<"*********8.求子串*******"<<endl;
	cout<<"*********9.串的定位*****"<<endl;
	cout<<"*********10.插入********"<<endl;
	cout<<"*********11.删除********"<<endl;
	cout<<"*********12.退出********"<<endl;
} 

int main()
{
	SString S;
	S.length = 0;//初始化长度为0
	char s[MaxLen];
	char t[512];
	int select;
	while(true)
	{
		ShowMenu();
		cout<<"请输入选项:";
		cin>>select; 
		switch(select)
		{
			case 1:
			{
				cout<<"请输入串的内容:";
				cin>>s;
				StrAssign(S,s);
				cout<<"串的内容为:";
				for(int i=1;i<=S.length;i++)
				{
					cout<<S.ch[i];
				}
				cout<<endl;
				system("pause");//请按任意键继续 
				system("cls");//清屏操作 
				break;
			}
			case 2:
			{
				cout<<"请输入要复制的串的内容:";
				cin>>s;
				StrCopy(S,s);
				cout<<"复制串的内容为:";
				for(int i=1;i<=S.length;i++)
				{
					cout<<S.ch[i];
				}
				cout<<endl;
				system("pause");
				system("cls");
				break;
			}
			case 3:
			{
				StrEmpty(S);
				system("pause");
				system("cls");
				break;
			}
			case 4:
			{
				cout<<"请输入要比较的串的内容:";
				cin>>s;
				StrCompare(S,s);
				system("pause");
				system("cls");
				break;
			}
			case 5:
			{
				StrLength(S);
				system("pause");
				system("cls");
				break;
			}
			case 6:
			{
				ClearString(S);
				system("pause");
				system("cls");
				break;
			}
			case 7:
			{
				cout<<"主串的内容为:";
				for(int i=1;i<=S.length;i++)
				{
					cout<<S.ch[i];
				}
				cout<<endl;
				cout<<"请输入子串的内容:";
				cin>>s;
				Concat(t,S,s);
				system("pause");
				system("cls");
				break;
			}
			case 8:
			{
				char Sub[MaxLen];
				int pos,len;
				cout<<"请输入要返回的位置起点:";
				cin>>pos;
				cout<<"请输入要返回的长度:";
				cin>>len;
				SubString(Sub,S,pos,len);
				system("pause");
				system("cls");
				break;
			}
			case 9:
			{
				SString T;
				T.length = 0;
				cout<<"请输入模式串:";
				char t[MaxLen];
				cin>>t;
				StrAssign(T,t);
				int next[T.length];
				cout<<"模式串的内容为:";
				for(int i=1;i<=T.length;i++)
				{
					cout<<T.ch[i];
				}
				cout<<endl;
				int pos;
				cout<<"请输入匹配的位置:";
				cin>>pos;
				Index(S,T,pos,next);
				system("pause");
				system("cls");
				break;
			}
			case 10:
			{
				int pos;
				cout<<"请输入要插入的位置:";
				cin>>pos;
				char t[MaxLen];
				cout<<"请输入要插入的字符串:";
				cin>>t;
				SString T;
				StrAssign(T,t);
				StrInsert(S,pos,T);
				system("pause");
				system("cls");
				break;
			}
			case 11:
			{
				int pos,len;
				cout<<"请输入要删除的位置:";
				cin>>pos;
				cout<<"请输入要删除的字符长度:";
				cin>>len;
				StrDelete(S,pos,len);
				system("pause");
				system("cls");
				break;
			}
			case 12:
			{
				cout<<"欢迎下次使用"<<endl;
				return 0;
			}
			default:
			{
				cout<<"欢迎下次使用"<<endl;
				return 0;
			}
		}
	} 

	return 0;
}

运行结果如下:
串

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值