#原创
之前老是对牛顿的“站在巨人肩膀上”有点误解,咱不否认牛顿在数学,物理上的才华与对人类的贡献,因为牛顿啥人品咱也都知道,误解他在所难免。现在发现杨绛先生的“你的问题主要在于读书不多而想得太多”愈发正确,书是人们智慧的载体,天才的存在使得书更有价值。多读书,站在巨人的肩膀上是有意义的,与其活在自己的世界里踽踽独行,不如包容的心态学习前人的经验。曾一直思考,其实岁月悠悠,哦,shit,大爷直接过来把自习室灯关了,我就一人还在这黑灯瞎火的抒情,咳咳,继续,说那儿了,,,,,(此处卡顿30s)哦,你思考的问题早有人为你思考过了,多看书是快速生长的一种方法,不用摸着石头过河了嘛!
废话不多说,看题,非计算机学生慎看。
编码工作常被运用于密文或压缩传输。这里我们用一种最简单的编码方式进行编码:把一些有规律的单词编成数宇。
字母表中共有26个字母{a,b,…,z},这些特殊的单词长度不超过6且字母按升序排列。把所有这样的单词放在一起,按字典顺序排列,一个单词的编码就对应着它在字典中的位置。
例如:
a→1 b→2 z→26 ab→27 ac→28
你的任务就是对于所给的单词,求出它的编码。
输入输出格式
输入格式:
仅一行,被编码的单词。
输出格式:
仅一行,对应的编码。如果单词不在字母表中,输出0。
输入样例 :ab 输出样例:27
该题目来源于洛谷,洛谷平台未标注出题作者
OK,进入正题,首先搞清升序与非递减的区别,即按字典序升序就保证了该编码制度下没有相同的字母。
所以a->1,b->2,c->3, ,z->26,aa->27,ab->28, , ,ba->53是错误的,也就是说不能看成由a~z组成的26进制编码成10进制,对吧?
Alright,发动你聪明的小脑瓜,抽象出该题背后的数据结构,想想它长什么样子了。
那些对“数据结构”概念一脸迷茫的孩子,可以继续阅读,牛犇可以略过。
数组结构的核心技术是分解和抽象。
首先对数据进行分解和抽象,通过分解划分出数据的层次(数据-数据元素-数据项);再经过抽象,舍弃数据元素的具体内容,得到数据的逻辑结构。
其次是处理的分解和抽象,通过分解将需求划分成各个功能;再经过抽象舍弃实现细节得到算法。
好吧,我也不罗嗦了,你肯定想掌握数据结构最重要的东西吧。
逻辑结构是你学数据结构必须掌握的,否则,嘿嘿嘿,你可能要叨念"Data structure fucks me"或者"Life sucks because of data structure "了。
逻辑结构分为线性结构和非线性结构。
线性结构元素之间的关系是一对一对的,如线性表,向量,栈(重要),队列(重要),优先队列,字典等。
非线性结构可能是一对多,即树(真重要),多对多,即图(真重要)本人觉得数据结构的博大精深从这儿开始就体现出来了。
/这是我的第一篇简书:-),还可以去gitee.com/cipolee/
下面是我理解的该题背后的结构。
理科男灵魂画师一个,不会画图,呜呜呜,,
哎哎哎,对了,这才叫抽象嘛,嘿嘿嘿,逻辑结构要的就是抽象。
image咳咳咳,前方高能。
每种逻辑结构背后都有,查找,遍历,插入,建立,删除。如果继续抽象,遍历属于查找,建立属于插入。
这个题不就是让你找到编码规律后为单词编码(第一步),存起来(第二步),然后给你个单词你往存起来的地方查找,找到你就能输出答案了,就这么easy。
第一步,编码规律你已经知道,就是上面的树,可以用DFS把树的每一条枝子(路径)即一个单词搜索一遍得到编码结果。
第二步,存起来,用什么存容易查找呢,还能代码容易实现,时间复杂度还低?
ummm,如果你够懒你会说我啥也不想用,就想给我单词我就能把编码输出。对!你这个想法很聪明,这时你会发现你需要一个由单词到数字的映射。用map存!
所有大的问题都解决,开始写代码,代码中出现的细节在代码里注释。
#include<iostream>
#include<map>
using namespace std;
map<string,int>M;//可以理解有一个M对象它从string字符串映射到一个整数及答案。
int cnt=1;
//cnt是计数器,初始a为1。
string all,one;
//all是为了给各个单词存编码而生成的所有种类的字符串(枚举的思想),而one是你要输入的字符串。
void DFS(int length,int k)//length是单词长度,k深搜的层数
{
if(k>length)//深搜边界
{
M[all]=cnt++;
return ;
}
char i,j;
if(k==1)
j='a';
else
j=all[k-2]+1;//k-2=k-1(回到上一层)-1(数组从0开始编号,找到上一个字母)+1(保证升序,大一个)
for(i=j;i<='z';i++)
{
all[k-1]=i;
DFS(len,k+1);
//为什么它就能按深搜的那个过程走一遍,你看执行到边界return,就回溯到上一层,上一层按顺序往后执行,然
//后依此类推
}
int main()
{
int n;//单词字母个数。
for(n=1;n<=6;n++)
{
all.clear();
all.resize(n);
DFS(n,1);
}
cin>>one;
cout<<M[one]<<endl;
return 0;
}
其实仔细思考DFS(depth first search深度优先搜索)和BFS(breadth first search广度优先搜索),就会发现其中的哲学思想,一个是一下子走到底,不到黄河不死心,玩深度;一个是先把最近的先走一遍,再往下走,重广度。
而栈,先进后出,队列,先进先出。这先进先出,先进后出所反映的思想在算法甚至在生活中也普遍存在。如果深度理解,你会发现DFS是栈的操作,BFS是队列的操作。
是不是发现这几行代码比一篇网络小说的信息量大多了。
新时代大学生,在每日巨大的信息冲击下,很难接受文艺的辞藻华丽的诗词,从接受信息获得快感的阈值越来越高,为此他们会浏览更多的信息,为此不浪费碎片的时间去看快手,抖音,在花花绿绿的信息流中接受须臾的感官刺激,垃圾信息害人太惨,代码中都是智慧的结晶,不仅包含的信息多,质量还高。
多读书不愿意?多读代码就好了。
image
网友评论