命名那个数字

GitHub跳转原题关系图返回列表

把单词按九键键盘映射成数字串,顺序扫描字典筛选出等于目标编号的单词。

OJ: roj

题目 ID: 2006

难度:入门

标签:模拟字符串

创建: 2026-10-01 02:27

更新: 2026-10-06 09:19

题目描述

经典九键电话键盘(不含 Q、Z):2 ABC / 3 DEF / 4 GHI / 5 JKL / 6 MNO / 7 PRS / 8 TUV / 9 WXY。 输入前部是字典中的大写单词(按字典序,少于 5000 个),最后一行是长度 1~12 的编号;输出所有按键映射后等于该编号的单词,每行一个,无解输出 NONE。 样例输入 4734,样例输出 GREG。

思路

字母到数字的映射是唯一的,所以不必从数字反向枚举字母,只需顺序扫描字典,把每个等长单词翻译成数字串并与编号比较。字典本身有序,输出天然按字典序。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-01 02:27
# update_at: 2026-10-04 11:16

import sys

# 九宫格键盘字符到数字的映射(不包含 Q 和 Z)
CHAR_TO_DIGIT = str.maketrans("ABCDEFGHIJKLMNOPRSTUVWXY", "222333444555666777888999")


def word_to_number(word: str) -> str:
    """将英文名字转换为九宫格按键数字串。"""
    return word.translate(CHAR_TO_DIGIT)


def find_matching_names(words: list[str], target: str) -> list[str]:
    """从字典单词列表中筛选出与目标数字匹配的所有名字。"""
    return [w for w in words if len(w) == len(target) and word_to_number(w) == target]


def solve() -> None:
    data = iter(sys.stdin.read().split())
    # 输入前部为字典名字列表,最后一个词为目标数字串:
    # 顺序消费时先拿首词当目标,之后每读到新词,就把旧目标降级为字典词
    target = next(data, "")
    if not target:
        return
    words: list[str] = []
    for token in data:
        words.append(target)
        target = token

    matches = find_matching_names(words, target)
    print("\n".join(matches) if matches else "NONE")


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-06 09:19
 * update_at: 2026-10-06 09:19
 */

#include <iostream>
#include <string>
using namespace std;

typedef long long ll;

const int MAXN = 5005;   // 字典中单词数量的上限
const int MAXL = 32;     // 单个单词与数字串的最大长度

string words[MAXN];      // 字典中的单词,输入时按字典序给出
char words_len[MAXN];    // 每个单词的长度,避免反复调用 size()
char digit_of[128];      // digit_of[ch] = 字母 ch 对应的按键数字字符

// 把单词的每个字母翻译成按键数字,结果写入 buf 并返回长度。
int word_to_digits(const string &w, char *buf) {
    int len = w.size();
    for (int i = 0; i < len; i++) {
        buf[i] = digit_of[(int)w[i]];
    }
    return len;
}

int main() {
    // 建立字母到按键数字的映射(Q 与 Z 不在键盘上)
    const char *letters = "ABCDEFGHIJKLMNOPRSTUVWXY";
    const char *digits = "222333444555666777888999";
    for (int i = 0; letters[i] != '\0'; i++) {
        digit_of[(int)letters[i]] = digits[i];
    }

    // 输入前部是字典单词,最后一个串是目标数字串
    int word_cnt = 0;
    string target;
    string token;
    if (!(cin >> target)) {
        return 0;   // 空输入不输出
    }
    while (cin >> token) {
        words[word_cnt] = target;
        words_len[word_cnt] = target.size();
        word_cnt++;
        target = token;
    }

    int target_len = target.size();
    char buf[MAXL];
    bool found = false;

    // 字典本身按字典序排列,顺序扫描得到的答案天然有序
    for (int i = 0; i < word_cnt; i++) {
        if (words_len[i] != target_len) {
            continue;
        }
        int len = word_to_digits(words[i], buf);
        bool same = true;
        for (int j = 0; j < len; j++) {
            if (buf[j] != target[j]) {
                same = false;
                break;
            }
        }
        if (same) {
            cout << words[i] << "\n";
            found = true;
        }
    }

    if (!found) {
        cout << "NONE" << "\n";
    }

    return 0;
}