华为OD机试 - 国际移动用户识别码(IMSI)匹配 - 递归(Python/JS/C/C++ 2025 C卷 200分)

在这里插入图片描述

2025C卷华为OD机试统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

一、题目描述

小明是核心网工程师,客户交给小明一个任务:给定一个网络配置列表,每个配置是一个字符串,仅有数字和"*“、”?"符号组成。

输入用户的IMSI(国际移动用户识别码),根据以下规则生成配置列表:

"*"匹配0个或多个任意字符。

"?“匹配下标为奇数的单个字符,比如123?中的”?"可以匹配123456789012345下标为3的字符’4’,下标从0开始。

二、输入描述

输入第一行为网络配置列表,列表中的每个配置由数字和*、?组成的字符串,每个字符串中*不超过一个,?若干,网络配置列表长度小于200,每个字符串以英文逗号隔开。

输入第二行为用户的IMSI(国际移动用户识别码),仅有数字组成,长度等于15。

备注

确保输入格式正确,无需考虑格式错误。

三、输出描述

输出为满足匹配规则的配置字符串列表,列表按照字典序升序输出,每个字符串以英文逗号隔开。若没有满足条件的配置,则返回字符串"null"。

四、测试用例

测试用例1:

1、输入

1234567,1234567*
123456789012345

2、输出

1234567*

3、说明

1234567长度不够无法匹配15位IMSI,1234567中的可以匹配剩余的89012345

测试用例2:

1、输入

123???345,123???*???345
123456789012345

2、输出

null

3、说明

123???345有16个字符,超过IMSI的15位
123???*???345中的?需要匹配奇数位置,但位置不对应

五、解题思路

1、主要解题思路

  1. 使用递归的方式实现配置字符串与IMSI的匹配
  2. 对于每个配置中的字符,根据其类型(数字、*、?)采用不同的匹配策略
  3. 特别处理*的回溯匹配,尝试匹配0个到多个字符
  4. ?只能匹配IMSI中下标为奇数位置的字符

2、数据结构:

ArrayList:存储所有匹配成功的配置字符串

String数组:存储分割后的配置列表

递归调用栈:用于回溯匹配

3、算法:

递归回溯算法:处理*的多种匹配可能性

字符串匹配算法:逐字符比对配置和IMSI

六、Python算法源码

def is_match(config, imsi):
    """
    判断配置是否能匹配IMSI
    :param config: 配置字符串
    :param imsi: IMSI字符串
    :return: 是否匹配
    """
    return match(config, 0, imsi, 0)

def match(config, c_idx, imsi, i_idx):
    """
    递归匹配函数
    :param config: 配置字符串
    :param c_idx: 配置字符串当前索引
    :param imsi: IMSI字符串
    :param i_idx: IMSI字符串当前索引
    :return: 是否匹配
    """
    # 如果配置字符串已经遍历完
    if c_idx == len(config):
        # 检查IMSI是否也遍历完
        return i_idx == len(imsi)
    
    # 获取当前配置字符
    c = config[c_idx]
    
    # 如果是*,尝试匹配0个或多个字符
    if c == '*':
        # 尝试匹配0个字符
        if match(config, c_idx + 1, imsi, i_idx):
            return True
        # 尝试匹配1个或多个字符
        for i in range(i_idx, len(imsi)):
            if match(config, c_idx + 1, imsi, i + 1):
                return True
        return False
    
    # 如果IMSI已经遍历完,但配置还有非*字符
    if i_idx >= len(imsi):
        return False
    
    # 如果是?,检查是否在奇数位置
    if c == '?':
        # 只有在IMSI的奇数位置才能匹配
        if i_idx % 2 == 1:
            return match(config, c_idx + 1, imsi, i_idx + 1)
        else:
            return False
    
    # 如果是数字,必须完全匹配
    if c == imsi[i_idx]:
        return match(config, c_idx + 1, imsi, i_idx + 1)
    
    return False

def main():
    # 读取网络配置列表
    config_line = input()
    configs = config_line.split(',')
    
    # 读取IMSI
    imsi = input()
    
    # 存储匹配成功的配置
    matched_configs = []
    
    # 遍历每个配置进行匹配
    for config in configs:
        if is_match(config, imsi):
            matched_configs.append(config)
    
    # 如果没有匹配的配置,输出null
    if not matched_configs:
        print("null")
    else:
        # 按字典序排序
        matched_configs.sort()
        # 输出结果,用逗号分隔
        print(','.join(matched_configs))

if __name__ == "__main__":
    main()

七、JavaScript算法源码

const readline = require('readline');

// 创建读取接口
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 存储输入行
let lines = [];

// 读取输入
rl.on('line', (line) => {
    lines.push(line);
    if (lines.length === 2) {
        // 处理输入
        processInput(lines[0], lines[1]);
        rl.close();
    }
});

/**
 * 处理输入并输出结果
 * @param {string} configLine - 配置列表字符串
 * @param {string} imsi - IMSI字符串
 */
function processInput(configLine, imsi) {
    // 分割配置列表
    const configs = configLine.split(',');
    
    // 存储匹配成功的配置
    const matchedConfigs = [];
    
    // 遍历每个配置进行匹配
    for (const config of configs) {
        if (isMatch(config, imsi)) {
            matchedConfigs.push(config);
        }
    }
    
    // 如果没有匹配的配置,输出null
    if (matchedConfigs.length === 0) {
        console.log("null");
    } else {
        // 按字典序排序
        matchedConfigs.sort();
        // 输出结果,用逗号分隔
        console.log(matchedConfigs.join(','));
    }
}

/**
 * 判断配置是否能匹配IMSI
 * @param {string} config - 配置字符串
 * @param {string} imsi - IMSI字符串
 * @returns {boolean} - 是否匹配
 */
function isMatch(config, imsi) {
    return match(config, 0, imsi, 0);
}

/**
 * 递归匹配函数
 * @param {string} config - 配置字符串
 * @param {number} cIdx - 配置字符串当前索引
 * @param {string} imsi - IMSI字符串
 * @param {number} iIdx - IMSI字符串当前索引
 * @returns {boolean} - 是否匹配
 */
function match(config, cIdx, imsi, iIdx) {
    // 如果配置字符串已经遍历完
    if (cIdx === config.length) {
        // 检查IMSI是否也遍历完
        return iIdx === imsi.length;
    }
    
    // 获取当前配置字符
    const c = config[cIdx];
    
    // 如果是*,尝试匹配0个或多个字符
    if (c === '*') {
        // 尝试匹配0个字符
        if (match(config, cIdx + 1, imsi, iIdx)) {
            return true;
        }
        // 尝试匹配1个或多个字符
        for (let i = iIdx; i < imsi.length; i++) {
            if (match(config, cIdx + 1, imsi, i + 1)) {
                return true;
            }
        }
        return false;
    }
    
    // 如果IMSI已经遍历完,但配置还有非*字符
    if (iIdx >= imsi.length) {
        return false;
    }
    
    // 如果是?,检查是否在奇数位置
    if (c === '?') {
        // 只有在IMSI的奇数位置才能匹配
        if (iIdx % 2 === 1) {
            return match(config, cIdx + 1, imsi, iIdx + 1);
        } else {
            return false;
        }
    }
    
    // 如果是数字,必须完全匹配
    if (c === imsi[iIdx]) {
        return match(config, cIdx + 1, imsi, iIdx + 1);
    }
    
    return false;
}

八、C算法源码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 最大配置长度
#define MAX_CONFIG_LEN 200
// 最大配置数量
#define MAX_CONFIG_COUNT 200

// 函数声明
int match(char* config, int cIdx, char* imsi, int iIdx);
int isMatch(char* config, char* imsi);
int compareStrings(const void* a, const void* b);

/**
 * 递归匹配函数
 * @param config 配置字符串
 * @param cIdx 配置字符串当前索引
 * @param imsi IMSI字符串
 * @param iIdx IMSI字符串当前索引
 * @return 是否匹配 (1: 匹配, 0: 不匹配)
 */
int match(char* config, int cIdx, char* imsi, int iIdx) {
    // 如果配置字符串已经遍历完
    if (config[cIdx] == '\0') {
        // 检查IMSI是否也遍历完
        return imsi[iIdx] == '\0';
    }
    
    // 获取当前配置字符
    char c = config[cIdx];
    
    // 如果是*,尝试匹配0个或多个字符
    if (c == '*') {
        // 尝试匹配0个字符
        if (match(config, cIdx + 1, imsi, iIdx)) {
            return 1;
        }
        // 尝试匹配1个或多个字符
        int i;
        for (i = iIdx; imsi[i] != '\0'; i++) {
            if (match(config, cIdx + 1, imsi, i + 1)) {
                return 1;
            }
        }
        return 0;
    }
    
    // 如果IMSI已经遍历完,但配置还有非*字符
    if (imsi[iIdx] == '\0') {
        return 0;
    }
    
    // 如果是?,检查是否在奇数位置
    if (c == '?') {
        // 只有在IMSI的奇数位置才能匹配
        if (iIdx % 2 == 1) {
            return match(config, cIdx + 1, imsi, iIdx + 1);
        } else {
            return 0;
        }
    }
    
    // 如果是数字,必须完全匹配
    if (c == imsi[iIdx]) {
        return match(config, cIdx + 1, imsi, iIdx + 1);
    }
    
    return 0;
}

/**
 * 判断配置是否能匹配IMSI
 * @param config 配置字符串
 * @param imsi IMSI字符串
 * @return 是否匹配 (1: 匹配, 0: 不匹配)
 */
int isMatch(char* config, char* imsi) {
    return match(config, 0, imsi, 0);
}

/**
 * 字符串比较函数,用于排序
 */
int compareStrings(const void* a, const void* b) {
    return strcmp(*(char**)a, *(char**)b);
}

int main() {
    char configLine[1000];  // 输入的配置行
    char imsi[16];          // IMSI (15位 + '\0')
    char* configs[MAX_CONFIG_COUNT];  // 配置数组
    char* matchedConfigs[MAX_CONFIG_COUNT];  // 匹配的配置数组
    int configCount = 0;    // 配置数量
    int matchedCount = 0;   // 匹配的配置数量
    
    // 读取配置行
    scanf("%s", configLine);
    // 读取IMSI
    scanf("%s", imsi);
    
    // 分割配置字符串
    char* token = strtok(configLine, ",");
    while (token != NULL && configCount < MAX_CONFIG_COUNT) {
        // 为每个配置分配内存
        configs[configCount] = (char*)malloc(strlen(token) + 1);
        strcpy(configs[configCount], token);
        configCount++;
        token = strtok(NULL, ",");
    }
    
    // 遍历每个配置进行匹配
    int i;
    for (i = 0; i < configCount; i++) {
        if (isMatch(configs[i], imsi)) {
            matchedConfigs[matchedCount++] = configs[i];
        }
    }
    
    // 如果没有匹配的配置,输出null
    if (matchedCount == 0) {
        printf("null\n");
    } else {
        // 按字典序排序
        qsort(matchedConfigs, matchedCount, sizeof(char*), compareStrings);
        
        // 输出结果,用逗号分隔
        for (i = 0; i < matchedCount; i++) {
            printf("%s", matchedConfigs[i]);
            if (i < matchedCount - 1) {
                printf(",");
            }
        }
        printf("\n");
    }
    
    // 释放内存
    for (i = 0; i < configCount; i++) {
        free(configs[i]);
    }
    
    return 0;
}

九、C++算法源码

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>

using namespace std;

/**
 * 递归匹配函数
 * @param config 配置字符串
 * @param cIdx 配置字符串当前索引
 * @param imsi IMSI字符串
 * @param iIdx IMSI字符串当前索引
 * @return 是否匹配
 */
bool match(const string& config, int cIdx, const string& imsi, int iIdx) {
    // 如果配置字符串已经遍历完
    if (cIdx == config.length()) {
        // 检查IMSI是否也遍历完
        return iIdx == imsi.length();
    }
    
    // 获取当前配置字符
    char c = config[cIdx];
    
    // 如果是*,尝试匹配0个或多个字符
    if (c == '*') {
        // 尝试匹配0个字符
        if (match(config, cIdx + 1, imsi, iIdx)) {
            return true;
        }
        // 尝试匹配1个或多个字符
        for (int i = iIdx; i < imsi.length(); i++) {
            if (match(config, cIdx + 1, imsi, i + 1)) {
                return true;
            }
        }
        return false;
    }
    
    // 如果IMSI已经遍历完,但配置还有非*字符
    if (iIdx >= imsi.length()) {
        return false;
    }
    
    // 如果是?,检查是否在奇数位置
    if (c == '?') {
        // 只有在IMSI的奇数位置才能匹配
        if (iIdx % 2 == 1) {
            return match(config, cIdx + 1, imsi, iIdx + 1);
        } else {
            return false;
        }
    }
    
    // 如果是数字,必须完全匹配
    if (c == imsi[iIdx]) {
        return match(config, cIdx + 1, imsi, iIdx + 1);
    }
    
    return false;
}

/**
 * 判断配置是否能匹配IMSI
 * @param config 配置字符串
 * @param imsi IMSI字符串
 * @return 是否匹配
 */
bool isMatch(const string& config, const string& imsi) {
    return match(config, 0, imsi, 0);
}

/**
 * 分割字符串函数
 * @param str 要分割的字符串
 * @param delimiter 分隔符
 * @return 分割后的字符串向量
 */
vector<string> split(const string& str, char delimiter) {
    vector<string> tokens;
    stringstream ss(str);
    string token;
    
    // 使用getline按分隔符分割
    while (getline(ss, token, delimiter)) {
        tokens.push_back(token);
    }
    
    return tokens;
}

int main() {
    string configLine;  // 配置行
    string imsi;        // IMSI
    
    // 读取输入
    getline(cin, configLine);
    getline(cin, imsi);
    
    // 分割配置字符串
    vector<string> configs = split(configLine, ',');
    
    // 存储匹配成功的配置
    vector<string> matchedConfigs;
    
    // 遍历每个配置进行匹配
    for (const string& config : configs) {
        if (isMatch(config, imsi)) {
            matchedConfigs.push_back(config);
        }
    }
    
    // 如果没有匹配的配置,输出null
    if (matchedConfigs.empty()) {
        cout << "null" << endl;
    } else {
        // 按字典序排序
        sort(matchedConfigs.begin(), matchedConfigs.end());
        
        // 输出结果,用逗号分隔
        for (int i = 0; i < matchedConfigs.size(); i++) {
            cout << matchedConfigs[i];
            if (i < matchedConfigs.size() - 1) {
                cout << ",";
            }
        }
        cout << endl;
    }
    
    return 0;
}

🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2025 C卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值