码蹄集2023部分题目

1🐋🐋🐋MC0204世界警察(黄金;双指针)

时间限制:4秒

占用内存:1024M

🐟题目描述

世界警察小码哥来谈判了,恐怖分子在银行挟持了 n 个人质,每个人质都所属一个国家,第 i 个人质所属的国家为 ci,人质排成了一排,位置都是固定的。经过商讨,恐怖分子允许小码哥可以带走任意一段连续区间内的人质。但是上级要求小码哥,最好每个国家的人质都带回来一个,不希望人质中有重复的国家。请问小码哥最多可以带出来多少人质。

🐟输入输出格式

复制代码
输入格式:
第一行一个正整数 n,表示共有 n 个人质;
第二行共有 n 个正整数,第 i 个正整数表示第 i 个人质的所属国家 ci。
​
输出格式:
一个整数表示小码哥最多可以带出来的人质数

🐟样例

🐚样例

复制代码
输入:
5
1 1 2 3 4
​
输出:
4

🐚备注

复制代码
其中:1≤n≤10^6;0≤ci≤10^9。

🐟题目思路

这道题目是典型的双指针区间问题,关键点在于如何发现重复数字以及如何处理重复数字:

  • 使用map的find功能查找该数字是否已存在;
  • 如果存在,那么结果区间只有两种情况:包含上一个和包含这一个。现在的情况就是包括上一个的情况,那么就直接判断长度;包含这一个(也就是现在右指针遇到的这个)的情况,那么该段的初始位置就是上一个该数字的下一个位置(+1)

⭐这里注意一点,也就是4的制胜点:在包含这一个的情况下,要额外判断这一个数是否已被放入到map当中。

🐟代码

cpp 复制代码
#include<bits/stdc++.h> 
​
using namespace std;
​
int main( )
{
    long long n;
    cin>>n;
    if(n==1) cout<<1<<endl;
    long long l=0,r=0;
    long long c;
    vector<long long> a;
    map<long long,long long> cur;
    int flag=0;
    for(long long i=0;i<n;i++) 
    {
        cin>>c;
        a.push_back(c);
        if(c!=a[0]) flag=1;
    }
    if(flag==0) cout<<1<<endl;
    cur.insert({a[0],0});
    long long ans=1;
    for(long long i=1;i<n;i++)
    {
        auto it=cur.find(a[i]);
        if(it==cur.end()) 
        {
            r++;
            cur.insert({a[i],i});
        }
        else
        {
            ans=max(ans,r-l+1);
            for(long long j=l;j<=it->second;j++) cur.erase(a[j]);
            l=it->second+1;
            if(cur.find(a[i])==cur.end()) cur.insert({a[i],i});//4的制胜点
            r++;
        }
    }
    ans=max(ans,r-l+1);
    cout<<ans<<endl;
    return 0;
}

2🐋🐋🐋MC0206小码哥的英语(白银;普通循环)

时间限制:1秒

占用内存:256M

🐟题目描述

小码哥在做英语单选题的时候突然想到了一个很有意思的问题:单选题的答案都是A或者B,那么很多道题目的答案组成的就是一个A和B组成的字符串。如果两个相邻的题目的答案是相同的,小码哥就可以修改这两个题目的答案,改成都是A、都是B或者一个是A另外一个是B,小码哥把这个定义为一次操作。那么对于任意一个答案字符串,最少需要多少次操作,才能使得它满足:任意相邻的题目的答案都不同。

🐟输入输出格式

复制代码
输入格式:
第一行包含一个数字 n (1≤n≤1000),表示字符串的个数;
后面的 n 行,每一行表示一个长度为L(1≤L≤10000)的,由字符A和B随机组成的字符串。
​
输出格式:
输出有多行,每一行表示对应字符串需要的最少的操作次数T(0≤T≤10000)。

🐟样例

复制代码
输入:
2
AAABAB
AABBBAB
​
输出:
1
2

🐟题目思路

乍一看这道题目,我以为是模拟过程,遇到两个相同的或三个相同的记为1,但是发现不对,一个点也过不了。后来受到forward---backward思想的启发,既然最后达到的状态是相邻两个字母不同,那么就只有两种可能:ABABAB和BABABA。基于此,我们只需要遍历字符串,然后和标准答案对比即可知道要做几次操作了。

🐟代码

cpp 复制代码
#include<bits/stdc++.h> 
​
using namespace std;
​
int main( )
{
    int n;
    cin>>n;
    string s;
    int ans1,ans2;
    for(int k=0;k<n;k++)
    {
        cin>>s;
        ans1=0;
        ans2=0;
        for(int i=0;i<s.size();i++)
        {
            if(i%2==0&&s[i]!='A') ans1++;
            if(i%2==1&&s[i]!='B') ans1++;
            if(i%2==0&&s[i]!='B') ans2++;
            if(i%2==1&&s[i]!='A') ans2++;
        }
        cout<<min(ans1,ans2)<<endl;
    }
    return 0;
}

3🐋🐋🐋MC0207中转站(黄金;简易版DFS)

时间限制:1秒

占用内存:256M

🐟题目描述

物流业为了降低物流成本,提高物流效率,运输过程中通常不会由始发地直达目的地,而是经由多个中转站中转,最终到达目的地。最常见的便是快递业,由于中转站有很多,要想将所有中转站两两互通代价过高,因此每个中转站只会与个别中转站单向或双向连通。

在接受订单时,为了判断该物件能否送达,会先查询本站是否能直接送达目的地站点;若不能,则递归查询本站可达中转站,以及中转站的中转站能否送达,直至找出目的地或找遍全部中转站。

🐟输入输出格式

复制代码
输入格式:
第一行输入两个正整数 n,m,n 是整个物流网所有中转站的数目,小码哥所在的站点是 1 号,目的地的站点是 n 号;
接下来的 m 行,每行输入两个正整数 x,y,代表中转站 x 可以送往中转站 y。
​
输出格式:
如果物件能够送达,输出”Yes”,否则输出”No”。

🐟样例

🐚样例1

复制代码
输入:
5 5
1 3
2 3
3 4
2 4
4 5
​
输出:
Yes

🐚样例2

复制代码
输入:
4 3
1 2
2 3
4 1
​
输出:
No

🐚备注

复制代码
其中:1<n≤500,1<m≤20000,1≤x,y≤n

🐟题目思路

题目很明显是想让我们用图遍历,这里主要是DFS深度优先遍历。但是DFS挺麻烦的(主要是我不太会😂),所以考虑一些更简单的方法。一个思路是,模拟DFS的过程,但是不使用迭代的方法:用数组p记录某一个点能否到达,也就是说,输入cur和next,如果p[cur]==1,那么意味着之前有路径能到达cur,那么自然p[next]就可以置为1了,意味着有路径可以到达next这一节点。

🐟代码

cpp 复制代码
#include<bits/stdc++.h> 
​
using namespace std;
​
int main( )
{
    int n,m;
    cin>>n>>m;
    vector<int> p(n+1,0);
    int cur,next;
    cin>>cur>>next;
    p[cur]=1;
    p[next]=1;
    m--;
    for(int i=0;i<m;i++)
    {
        cin>>cur>>next;
        if(p[cur]==1) p[next]=1;
    }
    if(p[n]==1) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
    return 0;
}

4🐋🐋🐋MC0210安全验证(钻石;KMP算法)

时间限制:1秒

占用内存:256M

🐟题目描述

小码哥是一名密码学专家,一天他的朋友拜托他设计一个简单的标识验证程序,用于服务器安全验证。

小码哥答应了朋友的请求,设计了一个简单的标识验证方法。服务器会自带一个安全标识串 S,每隔一段时间会自动更新,客户端的每次请求都会先收到服务器的标识串,然后在下一次更新前需要找出 S 中的一个真子串 T,满足既是 S 的前后缀,又在 S 中出现至少一次的最长串,找到后才能正常与服务器交互。

小码哥虽然精通密码学,但对开发一窍不通,于是找到了你,希望你能协助他完成程序开发环节。

🐟输入输出格式

复制代码
输入格式:
一个字符串 SS,全部是小写字母。
​
输出格式:
满足条件的最长真子串 TT,如果没有就输出”No”。

🐟样例

🐚样例1

复制代码
输入:
fixprefixsuffix
​
输出:
fix

🐚样例2

复制代码
输入:
abcdabc
​
输出:
No

🐚备注

复制代码
其中:3≤∣S∣≤10^6

🐟题目思路

题目给了比较明显的提示:最长前后缀。具体前后缀的介绍可以看我之前的一篇leetcode的内容:

⭐每天一道leetcode:28.找出字符串中第一个匹配项的下标(简单;暴力解;KMP算法,有难度)-CSDN博客

这道题目的思路就是:在KMP算法计算出前缀数组的基础上,判断除去前后缀部分的字符串是否仍包含这样至少一个前缀,如果是的那么输出这个前缀ans,否则输出No。这里判断是否包含,我是用了暴力求解的方法,也就是使用substr函数截取以i位置为起点的与ans等长度的子字符串,然后判断是否与ans相等。

🐟代码

cpp 复制代码
#include<bits/stdc++.h> 
​
using namespace std;
​
int main( )
{
    string s;
    cin>>s;
    vector<int> pi(s.size());
    for(int i=1,j=0;i<s.size();i++) //求s的前缀函数
    {
        while(j>0&&s[i]!=s[j]) 
        {
            j=pi[j-1];
        }
        if(s[i]==s[j]) j++;
        pi[i]=j;
    }
    string ans;
    //判断除了前后缀,中间部分是否还至少有一个前缀
    if(pi[s.size()-1]==0) cout<<"No"<<endl;
    else
    {
        for(int i=0;i<pi[s.size()-1];i++) ans+=s[i];
        if(s.size()-2*pi[s.size()-1]<pi[s.size()-1]) cout<<"No"<<endl;
        else 
        {
            for(int i=pi[s.size()-1]-1;i<s.size()-pi[s.size()-1];i++)
            {
                if(s.substr(i,ans.size())==ans) 
                {
                    cout<<ans<<endl;
                    return 0;//这里要用return,如果用break,后边那个No也会被输出出来;或者可以用break加一个flag标记一下
                }
            }
            cout<<"No"<<endl;
        }
    }
    return 0;
}

⭐点赞收藏不迷路~

相关推荐
励志成为嵌入式工程师37 分钟前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉1 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer1 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq1 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
wheeldown2 小时前
【数据结构】选择排序
数据结构·算法·排序算法
aloha_7892 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
青花瓷3 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
观音山保我别报错3 小时前
C语言扫雷小游戏
c语言·开发语言·算法
dsywws3 小时前
Linux学习笔记之vim入门
linux·笔记·学习
幺零九零零4 小时前
【C++】socket套接字编程
linux·服务器·网络·c++