一、实验目的:
(1)掌握串的顺序存储结构及定长字符串的基本操作。
(2)掌握串的BF和KMP模式匹配算法
二、实验原理
串是一种特殊的线性表,其特性体现在数据元素的一个字符,即串是一种内容受限的线性表。
定义:零个或者多个字符组成的有限序列。
子串:串中任意个连续的字符组成的子序列称为该串的字串。
主串:包含字串的串称为该字串的主串。
子串在主串中位置:字符在串中的序号称为该字符在串中的位置。
字符在主串中位置则以子串的第一个字符在主串中的位置表示。
串相等:两个串长度相等,且对应位置的字符也相等。
BF–蛮力算法(必须熟练掌握)
三、实验内容及步骤
1、建立顺序串结构。
2、输入串1和串2,在主函数中实现。输出串。
3、串的模式匹配。
4、串比较。比较串1和串2的大小,相等返回0,S1
6、串替换。输入串3,替换串1中包含的串2的所有内容。输出串1。
7、求子串。从串1中的第i个元素开始截取n个元素形成子串。输出子串。
四、实验源代码
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
#define FALSE 0
#define TRUE 1
#define MAXSIZE 50 /*初始分配的顺序串长度*/
typedef char ElemType; /*限定字符串元素值域必须为字符集*/
typedef struct string {
ElemType ch[MAXSIZE]; /*存储字符串的一维数组*/
int length; /*字符串的实际长度,不包括结束符*/
}SString;
SString* Create_SeqStr(char* s) /* 创建一个串,用字符串s初始化它 */
{
int i;
SString* pstr = (SString*)malloc(sizeof(SString)); /* 申请串空间 */
if (pstr == NULL)
printf("Out of space!!\n");
else {
pstr->length = 0;
for (i = 0; *s != '\0'; i++) //把串s存储到字符串pstr中,并输出字符串
{
//printf("%c,",*s);
pstr->ch[i] = *s++;//不会存‘\0’
pstr->length++;
}
return pstr;
}
}
/*遍历顺序串s的所有字符*/
void Traverse_SString(SString* S) {
int i;
for (i = 0; i<S->length; i++)
printf("%c", S->ch[i]);
printf("\n");
// return TRUE;
}/*TraverseList*/
/*1、串插入:在串S的第pos个字符处开始,插入串T*/
int SStrInsert(SString* S, int pos, const SString* T)
{
int i;
int j;
if (NULL == S || NULL == S->ch || NULL == T || pos<0 || pos>S->length)
return FALSE;
if (T->length+S->length<=MAXSIZE)//判断两个串长相加后是否溢出
{
for (i = S->length - 1; i >=pos - 1; i--) //先把S串中插入位置后的字符,移动位置
S->ch[i+T->length] = S->ch[i];
for (i = 0; i < T->length; i++) //把串T插入到串S的第pos位
S->ch[pos-1+i]=T->ch[i];
S->length=S->length+T->length; //串S长度更新
return TRUE;
}
else
return FALSE;
}
/*2、串删除:从串S中删除从第pos个字符开始连续len个字符后形成的子串*/
int SStrDelete(SString* S, int pos, int len)
{
int i;
if (NULL == S || NULL == S->ch || len < 0 || pos<0 || pos>S->length - len)
return FALSE;
else
{
for(i=pos-1+len; i<S->length; i++) //挪动元素实现从第pos个字符开始删除len个字符
S->ch[i-len]=S->ch[i];
S->length=S->length-len;//串S长度更新
return TRUE;
}
}
/*3、串连接:将串T的值连接在串S的后面*/
int SStrCat(SString* S, SString* T)
{
int i;
if (NULL == S || NULL == S->ch || NULL == T->ch)
return FALSE;
if (S->length+T->length<=MAXSIZE)//判断是否符合连接条件
{
for (i=0;i<T->length; i++)//把T中字符依次存入S中
S->ch[(S->length)+i] = T->ch[i];
S->length=S->length+T->length;//串长更新
return TRUE;
}
else
return FALSE;
}
/*4、求子串:截取串S中从第pos个字符开始连续len个字符形成的子串,并复制给串T*/
int SStrSub(SString* T, SString* S, int pos, int len)
{
int i;
if (NULL == S || NULL == S->ch || NULL == T || NULL == T->ch || len<0 || len>S->length - pos + 1 || pos<0 || pos>S->length)
return FALSE;
for (i = 0; i < len; i++)
T->ch[i] = S->ch[pos-1 + i];
T->length = len;//设置串T长度
return TRUE;
}
/*5、串比较:比较串S和串T的大小,S等于T返回0,S>T返回1,S
int SStrCompare(SString* S, SString* T)
{
int i;
if (NULL == S || NULL == S->ch || NULL == T || NULL == T->ch)
printf("串S或串T不存在,不能比较!\n");
else {
for (i = 0;i<T->length&&i<S->length; i++) //S和T中对应位置字符依次比较//T,S的length谁大谁小不明确
if (S->ch[i] != T->ch[i]) //判断比较是否进行
break;
if (i==T->length||i==S->length)//串S和串T相等
return 0;
if (S->ch[i]>T->ch[i])//串S>串T
return 1;
if (S->ch[i] < T->ch[i])//串S<串T
return -1;
}
}
/* 6、串匹配:蛮力(朴素)模式匹配算法:BF算法 */
/*在串S中第pos个字符处开始查找,串T是否存在,若存在,返回查找成功位序,否则返回FASLE*/
int SStrIndex_BF(SString* S, int pos, SString* T) {
int i, j;
if (NULL == S || NULL == S->ch || NULL == T || NULL == T->ch || pos<0 || pos>S->length)
return FALSE;
for (i=pos-1; i<S->length; i++)//设置查找区域
{
for (j = 0; j<T->length; j++) //从T中取出字符依次与S中字符比较
if (S->ch[i+j]!=T->ch[j]) //判断比较是否继续
break;
if (j==T->length)//查找成功,退出查找过程
break;
}
if (j!=T->length)//查找失败或i==S->length
return FALSE;
else
return i + 1;
}
/*7、串替换:在主串S中查找子串T,若找到并把子串T替换为子串V */
int SStrReplace(SString* S, SString* T, SString* V)
{
int i, j;
if (NULL == S || NULL == S->ch || NULL == T || NULL == T->ch || NULL == &V || NULL == V->ch)
return FALSE;
else
for (i = 0; i < S->length; i++)
{
j= SStrIndex_BF(S, i+1, T); //j用来存储,在串T中串S的位置
if (j!=FALSE) //判断是否具有替换的条件
{
SStrDelete(S, j, T->length); //SStrDelete(SString *S, int pos, int len),在串S中删除串T
SStrInsert(S, j, V); //SStrInsert(SString *S, int pos, const SString T),在串S中第j个位置开始插入串V
}
return TRUE;
}
}
int main() {
int i, j;
char str1[MAXSIZE];//=(char *)malloc(sizeof(char)*MAXSIZE) ;
char* str2 = (char*)malloc(sizeof(char) * MAXSIZE);
char* str3 = (char*)malloc(sizeof(char) * MAXSIZE);
SString* StrS = (SString*)malloc(sizeof(SString));
SString* StrT = (SString*)malloc(sizeof(SString));
SString* StrV = (SString*)malloc(sizeof(SString));
printf("\n ******************************************************************\n");
printf("\n *********************** 顺 序 串 常 用 算 法 *********************\n");
printf("\n ******************************************************************\n");
printf("\n1、串插入:在串S的第pos个字符处插入串T\n");
printf("请输入串S:");
scanf("%s", str1);
StrS = Create_SeqStr(str1);
printf("请输入串T:");
scanf("%s", str2);
StrT = Create_SeqStr(str2);
printf("请输入pos值:");
scanf("%d", &i);
if (SStrInsert(StrS, i, StrT))
{
printf("插入成功!\n遍历串S:");
Traverse_SString(StrS);
}
else
printf("插入失败!\n");
printf("\n\n2、串删除:从串S中删除从第pos个字符开始连续len个字符后形成的子串\n");
printf("请输入串S:");
scanf("%s", str1);
StrS = Create_SeqStr(str1);
printf("请输入pos值:");
scanf("%d", &i);
printf("请输入len值:");
scanf("%d", &j);
if (SStrDelete(StrS, i, j))
{
printf("删除成功!\n遍历串S:");
Traverse_SString(StrS);
}
else
printf("删除失败!\n");
printf("\n\n3、串连接:将串T的值连接在串S的后面\n");
printf("请输入串S:");
scanf("%s", str1);
StrS = Create_SeqStr(str1);
printf("请输入串T:");
scanf("%s", str2);
StrT = Create_SeqStr(str2);
if (SStrCat(StrS, StrT))
{
printf("连接成功!\n遍历串S:");
Traverse_SString(StrS);
}
else
printf("连接失败!\n");
printf("\n\n4、求子串:截取串S中从第pos个字符开始连续len个字符形成的子串,并复制给串T\n");
printf("请输入串S:");
scanf("%s", str1);
StrS = Create_SeqStr(str1);
StrT->length = 0;
printf("请输入pos值:");
scanf("%d", &i);
printf("请输入len值:");
scanf("%d", &j);
if (SStrSub(StrT, StrS, i, j))
{
printf("求子串成功!\n遍历串T:");
Traverse_SString(StrT);
}
else
printf("求子串失败!\n");
printf("\n\n5、串比较:比较串S和串T的大小,S等于T返回0,S>T返回1,S);
printf("请输入串S:");
scanf("%s", str1);
StrS = Create_SeqStr(str1);
printf("请输入串T:");
scanf("%s", str2);
StrT = Create_SeqStr(str2);
if (SStrCompare(StrS, StrT) == 0)
{
printf("串S等于串T\n");
/*Traverse_SString(StrS);
printf("等于");
printf("串T:");
Traverse_SString(StrT);*/
}
else
if (SStrCompare(StrS, StrT) == 1)
{
printf("串S大于串T\n");
/*Traverse_SString(StrS);
printf("");
printf(":");
Traverse_SString(StrT);*/
}
else
{
printf("串S小于串T\n");
/*Traverse_SString(StrS);
printf("小于");
printf("串T:");
Traverse_SString(StrT);*/
}
printf("\n\n6、串匹配:蛮力(BF)模式匹配算法:\n");
printf("在串S中第pos个字符处开始查找,串T是否存在,若存在,返回查找成功位序,否则返回FALSE\n");
printf("请输入串S:");
scanf("%s", str1);
StrS = Create_SeqStr(str1);
printf("请输入串T:");
scanf("%s", str2);
StrT = Create_SeqStr(str2);
printf("请输入pos值:");
scanf("%d", &i);
if (SStrIndex_BF(StrS, i, StrT))
{
printf("匹配成功!\n返回串T在串S中位序:");
printf(" %d\n", SStrIndex_BF(StrS, i, StrT));
}
else
printf("匹配失败!\n");
printf("\n\n7、串替换:在主串S中查找子串T,若找到并把子串T替换为子串V\n");
printf("请输入串S:");
scanf("%s", str1);
StrS = Create_SeqStr(str1);
printf("请输入串T:");
scanf("%s", str2);
StrT = Create_SeqStr(str2);
printf("请输入串V:");
scanf("%s", str3);
StrV = Create_SeqStr(str3);
if (SStrReplace(StrS, StrT, StrV))
{
printf("替换成功!\n遍历串S:");
Traverse_SString(StrS);
}
else
printf("插入失败!\n");
}
六、实验总结
1.串的结构体
typedef struct string {
ElemType ch[MAXSIZE];
int length;
}SString;
2.字符串的实际长度,不包括结束符,即串中不储存‘\0’,数组中每一个元素都为char型
3.这里的ElemType为char型
4.pos作为接口,指代第几个字符,返回的也是第几个字符(i+1),注意返回和使用的区别
5.串插入
for (i = S->length - 1; i >=pos - 1; i–) //先把S串中插入位置后的字符,移动T->length
S->ch[i+T->length] = S->ch[i];
for (i = 0; i < T->length; i++) //把串T插入到串S的第pos位
S->ch[pos-1+i]=T->ch[i];
6.串删除
for(i=pos-1+len; ilength; i++) //挪动元素实现从第pos个字符开始删除len个字符
T->ch[i-len]=S->ch[i];
7.插入删除等操作不能忘记更新length的值
8.串比较中T,S的length谁大谁小不明确,故两者的length均要考虑