【数据结构】第四章学习小结
串、数组
在第四章中,我学到的主要是关于串与数组的内容,至于广义表,既然老师让我们课后有时间去看,那我这里就先不讲广义表了(其实只是粗略的看了一下,还没看懂)
在上学期的c++中我就已经学过有关串的一些知识,对于串还是可以很好的理解的,在数据结构中,串将被看作是一种特殊的线性表,跟线性表一样,串也有两种基本存储结构,个人觉得顺序存储结构对于串的运用比较方便,简单易懂,所以在作业题中会首先考虑使用顺序串。
串有许多很重要的应用,例如搜索引擎,数据压缩等,这些应用都离不开串的模式匹配算法(子串的定位运算)
BF算法:1.利用计数指针i,和j指示主串S和模式串T当天正待比较的字符,将两者皆赋值为1;
2.将S[i]与T[j]比较,若两者相等,则将i,j分别指向串的下一字符,之后继续比较;
若不相等,指针就要后退重新匹配,主串回到i=i-j+2的位置上,模式串要回到j=1;(这就是BF算法的时间复杂度远远大于KMP算法的原因)
3.当j>模式串的长度时,说明匹配成功,此时返回和模式T中第一个字符相等的字符在主串S中的序号,否则返回0,级匹配失败。
优点:匹配过程易于理解,某些场合运行效率高
缺点:时间复杂度高
KMP算法:KMP算法看懂了觉得特别简单,思路很简单,看不懂之前,查各种资料,看的稀里糊涂,即使网上最简单的解释,依然看的稀里糊涂。(虽然说 现在还是有点迷糊。)
参考了下面的博客:KMP的最浅显理解 https://blog.csdn.net/starstar1992/article/details/54913261/
数组的话,主要研究的是二维数组的运用,在c语言中,二维数组采用的是以行序为主序的存储结构。特殊矩阵的压缩存储是二维数组的一种应用,这里可以使用三元组表和十字链表来解决(十字链表内容在第二章有)
三元组表:
typedef struct {
int row; //所在行
int column; //所在列
int value; //值
}Node; //定义三元组表
typedef struct {
int rows; //总行
int columns; //总列
int nums; //非零元素个数
Node data[100]; //非零元素 }tupleTable;
接下来就讲讲一些我对实践题第二题:估值上亿的AI这道题的一些理解吧
在听到老师说要教我们在星期四那节课上做出这道题,我是有点怀疑的,毕竟这可是天梯赛的题目,一些大佬都差点被难住了,我表示心里很慌。
当我看到题目的时候,莫名有一种很熟悉的感觉,仔细想想,这不是和上一周程序设计大赛上的一道题目很类似的吗,那时为了做出那道题想了贼久,可惜还是没做出来(哭)
题目
7-2 AI核心代码 (30 分)
本题要求你实现一个简易版的 AI 英文问答程序,规则是:
无论用户说什么,首先把对方说的话在一行中原样打印出来;
消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
把原文中所有大写英文字母变成小写,除了 I;
把原文中所有独立的 I 和 me 换成 you;
把原文中所有的问号 ? 换成惊叹号 !;
把原文中所有独立的 can you 换成 I can —— 这里“独立”是指被空格或标点符号分隔开的单词;
在一行中输出替换后的句子作为 AI 的回答。
输入格式:
输入首先在第一行给出不超过 10 的正整数 N,随后 N 行,每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话,对话为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。
输出格式:
按题面要求输出,每个 AI 的回答前要加上 AI: 和一个空格。
第一步:首先定义数据结构,自然是字符数组/字符串
最初考虑主函数逻辑,主要是读取输入语句,并调用接口处理输入语句并输出。
基本流程是,读入一句,对其进行扫描、判断、操作,再存到新的字符串,最后输出新的字符串。
int main() { int n; string a; cin>>n; getchar();/*吸收回车*/ for(int i=0;i<n;i++) { getline(cin,a); cout<<a<<endl; cout<<"AI: "; go(a);/*根据a输出AI的回答 */ } return 0; }
第二步:消除多余空格
for(i=0;a[i]!='\0'&&a[i]==' ';++i); ;/*最坏情况:全为空格,不会出现越界*/
第三步:对输入的语句进行处理:
void go(string a) {/*根据a输出AI的回答*/ char t[3002]; int i,j,k; /*i 定位到a的第一个非空*/ for(i=0;a[i]!='\0'&&a[i]==' ';++i); ;/*最坏情况:全为空格,不会出现越界*/ j=0; while(a[i]!='\0') { if(a[i]==' '&&a[i-1]==' ')/*把a串copy到t串,连续空格只copy一次*/ { ++i; continue; } if(a[i]=='?')/*把a串中的“?”换成“!”,写进t串中*/ { t[j]='!'; ++i; ++j; continue; } if(a[i]!='I')/*将“I”以外的大写字母统一变成小写字母*/ { t[j]=tolower(a[i]);++i;++j;/*tolower函数:将大写字母转成小写字母*/ continue; } t[j++]=a[i++]; } t[j]='\0';/*在t串后加上一个分隔符*/
这里用到了tolower()函数将大写变成小写。
将s串的有效都给了t串之后,我们可以遍历t串来进行进一步操作,比如将
独立的I和me变成you,有一点要特别注意要在t串之后加一个结尾符,否则会出现一大堆错误,乱码,之类的,很麻烦,当时改了好久,都没发现是这个问题
k=0; while(t[k]!='\0') { if(t[k]=='c'&&t[k+1]=='a'&&t[k+2]=='n'&&(k==0||IsIndependent(t[k-1]))&&IsIndependent(t[k+3])&&t[k+4]=='y'&&t[k+5]=='o'&&t[k+6]=='u'&&IsIndependent(t[k+7])) {/*把‘can you'换成’I can',同时k要加上'can you'的长度*/ cout<<"I can"; k=k+7; continue; } if(t[k]=='I'&&(k==0||IsIndependent(t[k-1]))&&IsIndependent(t[k+1]))/*将独立的‘I‘转成‘you’*/ { cout<<"you"; ++k; continue; } if(t[k]=='m'&&t[k+1]=='e'&&(k==0||IsIndependent(t[k-1]))&&IsIndependent(t[k+2])) /*将独立的‘me‘转成‘you’*/ { cout<<"you"; k=k+2; continue; } if(t[k]==' '&&IsIndependent(t[k+1])) { ++k; continue; } cout<<t[k]; ++k; } cout<<endl; }
以上是第四步,可以将独立的I 换成you独立的you 换成me,按照晓梅老师教给我们的思路,甚至可能是难点将can you 换成 I can 的操作也可以轻松写出来,
判断一个非空格字符是否独立的函数:
bool IsIndependent(char ch)/*判断当前字符是否独立*/ { ch=tolower(ch); if(ch>='0'&&ch<='9'||ch>='a'&&ch<='z') return false; else return true; }
将上述代码整合起来,PTA就基本上没问题了
心得体会:
在解这道题的过程中,我真正体会到了整个解题过程的思路是怎样一步一步出来,必须一个点一个点进行,在以后解题的时候也要学会在过程中对程序进行优化,及时指出错误与不足,学会自己梳理解题思路。
目标的完成情况:
这几周上课都能集中精力,基本没有出现走神的情况,课堂上的学习效果还算达到了预期目标,但是没有及时复习上一章的内容,有点遗憾,平时打的练习题还不够多。
接下来的目标:尽早扫除知识盲区,上次的测验已经给我敲响了警钟,接下来不仅要复习之前学习的内容,更要加把劲,将下一章的预习工作做好,继续去加深对KMP算法的理解。
- 用R语言对城管事件数据分析
- 使用dropwizard(4)-加入测试-jacoco代码覆盖率
- goldengate学习-安装篇(71天)
- 使用dropwizard(6)-国际化-easy-i18n
- 配置不同环境下启用swagger,在生产环境关闭swagger
- 使用ControllerAdvice注意事项,Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.
- rac节点无法启动ORA-29702的问题及分析(70天)
- SpringMVC,SpringBoot文件下载
- SpringCloud学习1-服务注册与发现(Eureka)
- 物化视图全量刷新与insert的redo生成量测试(69天)
- SpringCloud学习2-Springboot监控模块(actuator)
- 原码,反码,补码 与(&) 或(|) 非(~) 异或(^) 左移 << 右移 >> 无符号右移 >>>
- lombok使用基础教程
- 【Android基础】Android中的Intent详解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ubuntu16.04配置samba解决linux的svn使用舒适问题
- Erlang学习笔记(1)
- 结合公司现状浅谈CMDB
- SQLAlchemy使用
- 常用Oracle SQL集锦
- Python、PyGame游戏项目
- windows 认证机制
- 谷歌地球引擎python文档(GEE_python_API)
- react基础
- 基于ASP.NET Core 3.x的端点路由(Endpoint Routing)实现控制器(Controller)和操作(Action)分离的接口服务
- 流量转发映射
- 什么情况用ArrayList or LinkedList呢?
- 拒绝服务攻击
- 协议攻击(一)
- 百亿级图数据JanusGraph迁移之旅