【888题竞赛篇】第一题,2023睿抗-出院

更多精彩内容

这里是带你游历编程世界的Dashcoding编程社,我是Dash/北航硕士/ICPC区域赛全国排名30+/给你呈现我们眼中的世界!

256题算法特训课,帮你斩获大厂60W年薪offer

原题

2023睿抗-出院

B站动画详解

问题分析

该问题的核心是对输入的饮料名称进行分类,规则如下:

  1. 如果输入的是已知等级的饮料名称,直接输出该饮料对应的等级。
  2. 如果输入的饮料名称是由两个已知等级的饮料名称组合而成的,那么将两个部分的等级合并后输出,例如 Diet 的等级为 A,Coke 的等级为 D,那么 DietCoke 的等级为 AD。
  3. 如果输入的饮料名称既不是已知等级的饮料,也不能分解成两个已知的饮料组合,或者存在多种可能的分解方式,则默认输出 D 级。
    要实现这一目标,我们可以使用贪心和模拟的策略:在对饮料名称进行判断时,尽可能地优先考虑唯一的有效分解方案。

具体步骤如下:

  1. 首先,我们用哈希表存储所有已知饮料及其对应等级,以便快速查找。
  2. 然后,对于需要定级的每一个饮料,首先判断它是否在哈希表中存在,若存在则直接输出对应等级。
  3. 如果哈希表中不存在该饮料,则尝试将其分解为两个部分,并检查两部分是否都在哈希表中存在。若存在唯一的有效分解,则输出合并后的等级;否则,输出默认等级 D。

思路分析

该问题主要采用贪心和模拟的算法进行解决。由于题目中说明每个需要定级的饮料最多只能被分解为两个部分,因此我们可以用双指针遍历整个字符串,将其从不同位置进行分割,逐一检查分割后的两个部分是否均在已知饮料的哈希表中存在。

具体的算法流程如下:

对于每一个待定级的饮料:

  1. 若该饮料已经在哈希表中,直接输出其等级。
  2. 否则,从左到右遍历饮料名称,尝试将其分解为两个部分:
    1. 从索引 1 开始,尝试将饮料名称切分为两部分,分别判断这两部分是否均存在于哈希表中。
    2. 若存在唯一的有效分解方案,合并这两部分的等级并输出。
    3. 如果没有有效分解方案或存在多个可能的分解方式,则默认输出 D 级。

算法实现

  1. 使用哈希表 map<string,string> mp 存储已知饮料及其对应等级,确保查找的效率。
  2. 在处理需要定级的饮料时,首先检查是否存在于哈希表中,存在则直接输出。
  3. 如果不存在,则通过遍历尝试将饮料名称分割为两部分,并检查两部分是否均存在于哈希表中。
  4. 最后根据分解结果决定输出等级,如果没有找到唯一的有效分解,输出默认等级 D。

代码详解

标准代码程序

C++代码

#include<bits/stdc++.h>
using namespace std;
map<string,string>mp; // 存储已知饮料名称及其等级
int n, m; // n 表示已知饮料的数量,m 表示需要定级的饮料数量
int main(void) {
    cin >> n >> m;
    // 读取已知饮料及其等级
    for (int i = 0; i < n; i++) {
        string s1, s2;
        cin >> s1 >> s2;
        mp[s1] = s2;
    }
    // 处理需要定级的饮料
    for (int i = 0; i < m; i++) {
        if (i != 0)
            cout << endl;
        string s;
        cin >> s;
        // 1. 如果该饮料在已知等级中
        if (mp.count(s)) {
            cout << mp[s];
        } else {
            // 2. 尝试将其分解为两个部分
            int cnt = 0;  // 记录有效的分解次数
            string ans;
            for (int i = 1; i < s.size(); i++) {
                string s1 = s.substr(0, i); // 前半部分
                string s2 = s.substr(i); // 后半部分
                if (mp.count(s1) && mp.count(s2)) { // 检查两部分是否都在已知饮料中
                    cnt++;
                    ans = mp[s1] + mp[s2];
                }
            }
            // 如果没有有效分解或存在多种分解方式
            if (cnt == 0 || cnt > 1)
                cout << "D";
            else 
                cout << ans;
        }   
    }
    return 0;
}

Java代码

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        Map<String, String> map = new HashMap<>();
        
        for (int i = 0; i < n; i++) {
            String name = scanner.next();
            String level = scanner.next();
            map.put(name, level);
        }
        
        for (int i = 0; i < m; i++) {
            if (i != 0) System.out.println();
            String drink = scanner.next();
            
            if (map.containsKey(drink)) {
                System.out.print(map.get(drink));
            } else {
                int count = 0;
                String result = "D";
                for (int j = 1; j < drink.length(); j++) {
                    String part1 = drink.substring(0, j);
                    String part2 = drink.substring(j);
                    if (map.containsKey(part1) && map.containsKey(part2)) {
                        count++;
                        result = map.get(part1) + map.get(part2);
                    }
                }
                if (count == 1) {
                    System.out.print(result);
                } else {
                    System.out.print("D");
                }
            }
        }
    }
}

Python代码

def main():
    n, m = map(int, input().split())
    drink_map = {}
    
    for _ in range(n):
        name, level = input().split()
        drink_map[name] = level
    
    for _ in range(m):
        drink = input()
        if drink in drink_map:
            print(drink_map[drink])
        else:
            count = 0
            result = "D"
            for i in range(1, len(drink)):
                part1 = drink[:i]
                part2 = drink[i:]
                if part1 in drink_map and part2 in drink_map:
                    count += 1
                    result = drink_map[part1] + drink_map[part2]
            if count == 1:
                print(result)
            else:
                print("D")

if __name__ == "__main__":
    main()

Javascript代码

function main() {
    const readline = require('readline');
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });
    
    const input = [];
    rl.on('line', line => {
        input.push(line);
    }).on('close', () => {
        const [n, m] = input[0].split(' ').map(Number);
        const drinkMap = new Map();
        
        for (let i = 1; i <= n; i++) {
            const [name, level] = input[i].split(' ');
            drinkMap.set(name, level);
        }
        
        for (let i = n + 1; i < n + 1 + m; i++) {
            const drink = input[i];
            if (drinkMap.has(drink)) {
                console.log(drinkMap.get(drink));
            } else {
                let count = 0;
                let result = "D";
                for (let j = 1; j < drink.length; j++) {
                    const part1 = drink.slice(0, j);
                    const part2 = drink.slice(j);
                    if (drinkMap.has(part1) && drinkMap.has(part2)) {
                        count++;
                        result = drinkMap.get(part1) + drinkMap.get(part2);
                    }
                }
                if (count === 1) {
                    console.log(result);
                } else {
                    console.log("D");
                }
            }
        }
    });
}

main();

复杂度分析

时间复杂度分析

  1. 初始化部分:
  • 读取已知饮料信息并将其存入哈希表需要 O ( N ) O(N) O(N) 的时间,其中 N N N 是已知饮料的数量。
  1. 查询部分:
  • 对每一个需要定级的饮料(共 M M M 个):
    • 首先判断该饮料是否在哈希表中,这一步的时间复杂度为 O ( 1 ) O(1) O(1)
    • 如果不在哈希表中,则需要尝试将该饮料名称拆分为两部分。假设待定级饮料的长度为 L L L,我们需要进行 L − 1 L-1 L1 次分割,每次分割需要检查两部分是否存在于哈希表中,这里的时间复杂度为 O ( L ) O(L) O(L)

因此,处理每个待定级饮料的最坏情况时间复杂度为 O ( M × L ) O(M \times L) O(M×L)

空间复杂度分析

  1. 用于存储已知饮料及其对应等级的哈希表需要 O ( N ) O(N) O(N) 的空间,其中 N N N 是已知饮料的数量。
  2. 需要定级的饮料字符串在存储时需要 O ( M × L ) O(M \times L) O(M×L) 的空间,其中 M M M 是需要定级的饮料数量, L L L 是饮料名称的平均长度。

综上,空间复杂度为 O ( N + M × L ) O(N + M \times L) O(N+M×L)

总结

该问题的关键在于如何高效地对饮料名称进行分割和查找。通过使用哈希表,我们能够在常数时间内查找已知饮料及其对应等级。在处理待定级的饮料时,采用双指针将名称从不同位置进行分割,并通过哈希表判断分割后的两部分是否均在已知饮料中存在,这样的方式有效地减少了时间复杂度。

算法的整体效率相对较高,适用于输入规模较大的场景。即使在最坏情况下,算法的时间复杂度也能够控制在 O ( M × L ) O(M \times L) O(M×L),而哈希表的使用确保了查找操作的高效性。

本题目展示了贪心策略和模拟方法在解决组合拆分问题中的应用,是一个典型的考察字符串处理、哈希查找和算法设计的编程题目。

  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值