西南交通大学【数据结构实验4】
动态存储分配采用C++的new和delete操作符实现;输入与输出采用C++的文件流对象和cout流;程序注释采用C/C++规范。从键盘输入主串s以及子串t1和t2。编写程序,将主串s中所有t1子串替换为t2子串,输出替换后得到的串以及t1被替换的次数。要求子串查找采用改进KMP算法。输入:根据提示在键盘上输入主串s、子串t1、子串t2。输入:采用遍历数组的方式将串中所有字符输出。程序输出结果与期
实验内容及要求:
从键盘输入主串s以及子串t1和t2。编写程序,将主串s中所有t1子串替换为t2子串,输出替换后得到的串以及t1被替换的次数。要求子串查找采用改进KMP算法。
实验目的:掌握KMP算法。
数据结构设计简要描述:
采用一个定长数组和一个长度变量组成结构体
// 定义串,最大容量255,第一个位置不放元素
typedef struct {
char s[256];
int length;
}SString;
算法设计简要描述:
采用kmp算法去匹配t1,未改进的next函数将next值存储到next数组中
输入/输出设计简要描述:
输入:根据提示在键盘上输入主串s、子串t1、子串t2
输入:采用遍历数组的方式将串中所有字符输出
编程语言说明:
使用Visual Studio Code编程。 主要代码采用C语言实现 ;动态存储分配采用C++的new和delete操作符实现;输入与输出采用C++的文件流对象和cout流;程序注释采用C/C++规范。
主要函数说明:
// 从键盘录入字符,完成三个串的初始化
void get_str(SString& s, SString& t1, SString& t2);
// kmp算法
int kmp(SString s, SString t, int pos, int next[]);
// 求next值并存入next数组
void Next(SString t, int next[]);
// 替换时主串其他字符移动情况
void move(SString& s, int pos, int dis);
// 输出串所有字符
void print(SString& s);
程序测试简要报告:
- 测试实例1
程序输入
s:aaaaaaa
t1:aa
t2:abc
程序输出

结论
程序输出结果与期望输出结果相符。
- 测试实例2
程序输入
s:ababvab
t1:ab
t2:aa
程序输出

结论
程序输出结果与期望输出结果相符。
- 测试实例3
程序输入
s:abcab
t1:ab
t2:c
程序输出

结论
程序输出结果与期望输出结果相符。
源代码:
#include <iostream>
using namespace std;
// 定义串,最大容量255,第一个位置不放元素
typedef struct {
char s[256];
int length;
}SString;
// 从键盘录入字符,完成三个串的初始化
void get_str(SString& s, SString& t1, SString& t2) {
// 定义字符变量,读取缓冲区字符
char ch;
// 记录串长度
int count = 0;
cout << "请输入主串s:" << endl;
// 一次读取一个字符
ch = getchar();
// 当没读到换行符和长度小于255时进入循环
while (ch != '\n' && count < 255)
{
++count;
s.s[count] = ch;
ch = getchar();
}
// 一个串读取完毕,将长度赋值
s.length = count;
// t1和t2子串的读取和主串s的读取一致
count = 0;
cout << "请输入子串t1:" << endl;
ch = getchar();
while (ch != '\n' && count < 255)
{
++count;
t1.s[count] = ch;
ch = getchar();
}
t1.length = count;
count = 0;
cout << "请输入子串t2:" << endl;
ch = getchar();
while (ch != '\n' && count < 255)
{
++count;
t2.s[count] = ch;
ch = getchar();
}
t2.length = count;
}
// kmp算法
int kmp(SString s, SString t, int pos, int next[]) {
// 利用模式串t的next函数求t在主串s中第pos个字符之后的位置
// 其中t非空,1<=pos<=s.length
int i = pos, j = 1;
// 两个串均未比较到串尾
while (i <= s.length && j <= t.length)
{
// 继续比较后继字符
if (s.s[i] == t.s[j] || j == 0) {
++i;
++j;
}
else {
// 模式串向右移动
j = next[j];
}
}
// 匹配成功
if (j > t.length) {
return i - t.length;
}
else {
// 匹配失败
return 0;
}
}
// 求next值并存入next数组
void Next(SString t, int next[]) {
int i = 1, j = 0;
next[1] = 0;
while (i <= t.length)
{
if (j == 0 || t.s[i] == t.s[j]) {
++i;
++j;
next[i] = j;
}
else {
j = next[j];
}
}
}
// 替换时主串其他字符移动情况
void move(SString& s, int pos, int dis) {
// 如果t1和t2长度一样,其他字符不用移动
if (!dis) {
return;
}
// t2串比t1串长,匹配成功的t1串后的字符向后移
if (dis > 0) {
int i;
if (s.length + dis > 255) {
i = 255 - dis;
}
else {
i = s.length;
}
while (i >= pos)
{
s.s[i + dis] = s.s[i];
--i;
}
s.length += dis;
}
else {
// t1串比t2串长,匹配成功的t1串后的字符向前移
dis = -dis;
while (pos <= s.length)
{
s.s[pos - dis] = s.s[pos];
++pos;
}
s.length -= dis;
}
}
// 输出串所有字符
void print(SString& s) {
for (int i = 1; i <= s.length; ++i) {
cout << s.s[i];
}
}
int main(void) {
// 定义串
SString s, t1, t2;
// 定义 start:匹配开始位置 begin:替换开始位置 length_dif:t1和t2长度之差 count:替换次数
int start = 1, begin, length_dif, count = 0;
// 定义next数组
int next[256];
get_str(s, t1, t2);
length_dif = t2.length - t1.length;
Next(t1, next);
while (1)
{
// 得到替换开始位置
begin = kmp(s, t1, start, next);
// 如果未找到退出循环
if (!begin) {
break;
}
++count;
// 下一次的匹配开始位置
start = begin + t2.length;
// 移动后续的字符
move(s, begin + t1.length, length_dif);
// t2串替换t1串
for (int i = 1; i <= t2.length; ++i, ++begin) {
s.s[begin] = t2.s[i];
}
}
// 输出结果
cout << "替换后的s: ";
print(s);
cout << " 替换次数: " << count << endl;
return 0;
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)