| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 【第九题】礼物(北理工/北京理工大学/程序设计方法与实践/小学期) -> 正文阅读 |
|
[数据结构与算法]【第九题】礼物(北理工/北京理工大学/程序设计方法与实践/小学期) |
目录 前言本文面向无竞赛或者算法基础的人,或者说,当你来搜这个题目的时候,我就默认你没有相关基础了。为什么写这篇博客呢?其实我觉得我是不配的,但是csdn上我这篇大概将会成为唯一一篇这道题的题解。(之前是有一篇的,但是因为题目有一些变化,所以那篇文章已经可以说是过时了) 建议顺着把文章看完,我个人理解,如果可以跳过前面直接到后面,那也不会面向CSDN编程了。 本人平平无奇,所以不会出现大佬们的视角盲区,各位平起平坐,放心食用,不用担心看不懂之类的。 我的基础具体说,只有假期自己看了300页c primer plus的基础,不会c++,不会STL,不会算法,只会c语言基础语法一把梭,大家可以对接一下自己的水平,我觉得这就是个中等水平。 我想说的是,不会可以学,不会并不代表不能会,英雄不问出处,请坚持住! 这道题搞了我几个小时,终于是完美地AC了,现在回头敲出来不会花很长时间,其实时间都花在学习新知识上了,下一道题根据@贝贝今天AC了吗 的文章,还要学数据结构的栈,头秃,就当是提前学吧,反正这小学期就是个提取学习,见到啥学啥。 本题解不是最优解,好在思路比较清晰,能稳定通过全部案例。 题干:【礼物】Description 小张的好朋友小松要过生日了,小张打算为他挑选一件礼物。在市场上他发现有一个珠子手镯的商店很不错。在这家商店会出售特殊的珠子并穿成一个手镯,在货架上珠子排成一排,每一个珠子上有一个小写英文字母。店家有一个特殊的规定,必须在一排珠子中按顺序从左到右挑选。小张心中已经有一个想要送给小松的单词,请你告诉他应该如何挑选珠子使得手镯上珠子的字母组成小张想要的单词。 Input 第一行,一个字符串,表示货架上的一排珠子,仅包含小写英文字母,长度在200000以内。 第二行,一个字符串,表示小张想要的单词,仅包含小写英文字母,长度在10000以内。 Output 输出一行整数,表示小张按照从左到右需要挑选的珠子在货架上的位置。 Notes 从左到右按顺序选出的珠子上的字母为'p','p','y','h','a'。串成环形的手镯后可以组成"happy"。 数据保证有解,若有多种选取方法,输出其中字典序最小的一个,比如1 2 3 4比1 3 4 5的字典序小。 提交后查看结果页面错误信息一栏,前4行的编译错误大家不用理会,第5行是关于你的结果的信息。 测试用例:input ????????pxrtpsapyjhuvab ????????happy output ????????1?5?9?11?14 心路历程1 自己尝试TLE其实这道题乍一看很简单,不就是遍历吗。 然而TLE路上等你,说多了都是泪。 2 论坛无果论坛的信息太过零散,大多是一种个人总结,带有装逼性质的那种,顺便混点分。这种不会讲太细,看不懂是很正常的。比如下面这个,现在回头看,他说的都是非常正确的,而且是很关键的,但是当时怎么就看不懂呢?关键出在基础知识上。 3 柳暗花明无意间看到有人说子序列自动机,我依稀想起舍友之前和我说过这个东西。 当时舍友和我说的时候我上csdn看了看,感觉太难了,就没再看过,结果最后碰的头破血流,回头发现当时看起来最难的东西,可以说几乎是做出这道题AC的唯一途径,否则就是TLE。 于是就开始漫长的子序列自动机的学习。 子序列自动机怎么学?1 为什么要子序列自动机?逐字符遍历耗时太久,我们需要跳跃。 跳到哪里呢?比如我要找happy,我现在已经找到了h,那我能不能直接跳到后面第一个a呢?可以,只要我们储存了那个a的编号就可以,子序列自动机应运而生。 2 学习资料https://blog.csdn.net/qq_43109145/article/details/89429411?spm=1001.2014.3001.5506 这篇文章因为有图解,所以比较清晰易懂,但是有一个重大缺陷,那就是这个程序会跑错(破防),也就是说,她的思想是对的,但是有细节错误,所以这篇文章就供大家建立对子序列自动机的基本认识:横坐标代表什么?纵坐标代表什么?如何根据给出的带筛选字符串构造一个子序列自动机二维数组?如何用取出来的一种环(比如appyh)去跳跃遍历这个子序列自动机? 剩下的文章,大家也可以搜着看,核心都是一样的,就是建立自动机,然后遍历。 3 补充思路其实要看懂自动机,最好还是有个思路在前。如果没有一个宏观思路,那么去看代码很容易只见树木不见森林,这里提供一下宏观思路: 首先要遍历所有可能的组合,类似:happy,appyh,直到yhapp 我们可以使用happyhappy字符串,从h到y每次顺次读取5个字符就可以实现,如果不想扩展字符串也可以用%运算来实现模仿环形。 对于每一种可能的5个字符,要在自动机中遍历,自动机的作用简单说就是加快遍历的速度,从一个一个遍历,到跳跃遍历。 好,如果能成功遍历到我们目标的5个字符,那么这个组合就是有解的。 之后就要判断是否是最优解了,这里要用一个ans数组储存最终的答案,用temp数组去做缓冲。这里涉及到一个字典序的的定义,字典序大家百度一下,其实就是类似于strcmp函数,只不过我们比较的内容超出了char范围,所以手写一个对int生效的“intcmp”函数,如果temp的字典序小于ans,那么就是更优解,那么就把temp写入ans,以此类推。 最后输出ans即可,因为不断优化,最后剩下的就是最优解了。 好的,到这里,就把大致的思路介绍完了,那么之后无论是学习子序列自动机或者看我的代码,都可以比较容易的看懂。 代码请注意,不要ctrl c+v,不要ctrl c+v,不要ctrl c+v!!!! 懂的都懂,查重直接爆炸,扣十分可能直接挂科,。 至少改变量,加自己的想法,或者尝试把自动机写成不包括自己的形式,都可以。我想,能来北理工的,怎么也得有点傲骨的吧,看我的代码是作为参考,抄就是人格的问题了。 如果你真的想学会这个知识点的话,建议你看懂我的代码后自己敲出来,或者对着我的代码先敲一遍,一边敲一边打注释,来辅助理解,最后删掉再自己敲出来,那就算是学会了。 我加了很多注释,这些注释其实是我在学习过程中记录的思考,同时大大提高程序可读性,大概csdn上像我这样几乎一句一个注释的二五仔少得很吧,但是为了理解,脸可以先放一边。
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/30 0:49:10- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |