//串的基本操作:赋值,复制,串空判断,比较,统计串长,清空串,拼接串,返回子串
//插入和删除以及定位和模式匹配(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;
}
运行结果如下:

该代码实现了串的顺序存储结构,包括赋值、复制、判断串空、比较、统计串长、清空、拼接和返回子串等基本操作。此外,还包含了BF暴力匹配和KMP模式匹配算法,用于字符串的定位。程序提供了一个简单的交互式菜单供用户选择执行不同的操作。
3397





