【洛谷刷题 | 第五天】

本系列文章我将总结我在刷算法题所用到的知识,如果你也在刷算法并且是新手,我相信这系列文章会很适合你。

【洛谷刷题 | 第五天】

    • 今日题目:
      • [1.[COCI 2017/2018 #2] ​​ZigZag(字符串,排序)](#2] ZigZag(字符串,排序))
      • [2. 国王的魔镜(模拟,字符串,搜索,递归)](#2. 国王的魔镜(模拟,字符串,搜索,递归))

今日题目:

1.[COCI 2017/2018 #2] ​​ZigZag(字符串,排序)

链接:P4432 [COCI 2017/2018 #2] ​​ZigZag

给你一堆单词,再给你一串首字母查询。每次查一个字母,你要在以这个字母开头的单词里,选出用得次数最少的那个;如果次数一样,就选字典序最小的,选完把这个单词的计数 + 1,最后输出每次选的单词。

案例:

cpp 复制代码
输入                                输出
4 5                                zadar
zagreb                             sisak
split                              split
zadar                              zagreb
sisak                               zadar
z
s
s
z
z

这道题主要用了按首字母分组 + 字典序排序 + 轮询选取的思想。最开始我想着是把所有字符串都按字典序排序,但后面才了解掌握到把每个按首字母分组分别排序的方法;排完序后可以为每个首字母分组维护一个指针,每次查询对应首字母时,指针向后移动(若超出该组单词数量则重置为 1),直接输出指针指向的单词即可。

题解:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
string s[30][10009],S;
int p[30],num[30];
char ch;
int main()
{
    int k,n;
    cin>>k>>n;
    for(int i=0;i<k;i++){
        cin>>S;
        int t = S[0]-'a'+1;
        s[t][++num[t]] = S;//注意是先++而不是后++
    }
    for(int i=1;i<=26;i++)
    {
        sort(s[i]+1,s[i]+1+num[i]);
    }
    while(n--){
        ch=getchar();
        while(ch<'a'||ch>'z') ch = getchar();
        int x = ch-'a'+1;
        p[x]++;
        if(p[x]>num[x]) p[x]=1;
        cout<<s[x][p[x]]<<'\n';
    }
}
知识点:字符串

1.字典序排序规则

从单词的第一个字符开始比,字符小的单词整体更小(比如 apple < banana,因为 a 在字母表里比 b 靠前);

如果第一个字符相同,就比第二个字符(比如 apple < apply,前 4 个字符都一样,第 5 个 e < y);

以此类推,直到比出第一个不同的字符;

如果一个单词是另一个的前缀(比如 app 和 apple),则短的单词更小。

2.如何排序:

跟数组一样用sort就可以从小到大将字符串按照字典序排序。

像这到题string s[30][10009] 是二维字符串数组,第一维对应 26 个字母分组,第二维对应组内单词的位置。

s[1][10009] 就表示 a 开头的第 10009 个单词

cpp 复制代码
 for(int i=1;i<=26;i++)
    {
        sort(s[i]+1,s[i]+1+num[i]);
    }

这个代码的作用就是:把每个首字母(a-z)对应的所有单词,单独整理成 "字典序从小到大" 的顺序。

3.getchar

getchar() 是 C/C++ 里的一个输入函数,核心作用是:从输入读取一个字符(包括空格、换行、Tab 这些看不见的字符),相比 cin,getchar() 更底层、更灵活,适合需要精准控制输入的场景。

2. 国王的魔镜(模拟,字符串,搜索,递归)

链接:P2799 国王的魔镜

给一个由大写字母组成的最终项链字符串(是通过 "每次把一端接触魔镜,让项链长度翻倍且新增部分反转" 得到的),求最初项链的最小可能长度。

案例:

cpp 复制代码
输入                               输出
ABBAABBA                           2

从最终的字符串不断往前倒推:每次检查当前字符串是不是前后对称,如果对称,就说明它是由前半段用魔镜变出来的,那就只保留前半段继续检查;如果不对称或者长度是奇数,就不能再缩小了,此时的长度就是最初项链的最小长度。

题解:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
string s;
int p(int x){
    if((x+1)%2==1) return x+1;
    if(x==0) return 1;
    int le = 0;int re = x;
    while(le<re){
        if(s[le]!=s[re])
        		  return x+1;
              le++;re--;
                }
     return p(re);
}
int main()
{
    cin>>s;
    int n = s.size();
    cout<<p(n-1);
}
知识点:递归

什么是递归:

递归就是函数自己调用自己,核心逻辑是 "把复杂问题拆成和原问题相似但规模更小的子问题",直到子问题简单到能直接解决,再从子问题的答案推导出原问题的答案。

总结:

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

相关推荐
cmpxr_7 小时前
【C】数组名、函数名的特殊
c语言·算法
KAU的云实验台7 小时前
【算法精解】AIR期刊算法IAGWO:引入速度概念与逆多元二次权重,可应对高维/工程问题(附Matlab源码)
开发语言·算法·matlab
会编程的土豆7 小时前
【数据结构与算法】再次全面了解LCS底层
开发语言·数据结构·c++·算法
大熊背8 小时前
如何利用Lv值实现三级降帧
算法·自动曝光·lv·isppipeline
大尚来也9 小时前
驾驭并发:.NET多线程编程的挑战与破局之道
java·前端·算法
向阳而生,一路生花9 小时前
深入浅出 JDK7 HashMap 源码分析
算法·哈希算法
君义_noip9 小时前
信息学奥赛一本通 4150:【GESP2509七级】⾦币收集 | 洛谷 P14078 [GESP202509 七级] 金币收集
c++·算法·gesp·信息学奥赛·csp-s
摸个小yu9 小时前
【力扣LeetCode热题h100】链表、二叉树
算法·leetcode·链表
汀、人工智能9 小时前
[特殊字符] 第93课:太平洋大西洋水流问题
数据结构·算法·数据库架构·图论·bfs·太平洋大西洋水流问题
ZPC82109 小时前
rviz2 仿真控制器与真实机器人切换
人工智能·算法·机器人