编号7题解 | 豆包MarsCode AI 刷题

110 阅读4分钟

题目

在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创建标题时使用通配符。通配符用成对的 {} 括起来,可以包含0个或多个字符。线上服务时,会根据用户的搜索词触发的 bidword 对创意中的通配符进行替换,用来提升广告投放体验。例如,创意 "末日血战} 上线送 SSR 英雄,三天集齐无敌阵容!" 可以被替换成 "帝国时代游戏下载上线送 SSR 英雄,三天集齐无敌阵容!"

题目描述

给定一个含有通配符的创意和 n 个标题,判断这些标题是否是从该创意替换生成的。通配符 {} 可以匹配任意长度的字符串,包括空字符串。

解题思路

  1. 提取模板中的固定部分和通配符部分

    • 遍历模板字符串,提取固定部分和通配符部分。
    • 固定部分是指不在 {} 中的部分,通配符部分是指在 {} 中的部分。
  2. 匹配标题

    • 使用递归函数 match 来匹配标题。
    • 对于固定部分,检查标题是否以该固定部分开头。
    • 对于通配符部分,尝试匹配任意长度的字符串,递归检查剩余部分。
  3. 处理异常情况

    • 确保模板中没有嵌套的通配符。
    • 确保模板中的通配符成对出现。

代码详解

提取模板中的固定部分和通配符部分
def is_generated_from_template(template, title):
    # 提取模板中的固定部分和通配符部分
    parts = []
    buffer = []
    in_wildcard = False

    for char in template:
        if char == '{':
            if in_wildcard:
                raise ValueError("Nested wildcards are not allowed.")
            if buffer:
                parts.append(('fixed', ''.join(buffer)))
                buffer = []
            in_wildcard = True
        elif char == '}':
            if not in_wildcard:
                raise ValueError("Unmatched closing wildcard bracket.")
            if buffer:
                parts.append(('wildcard', ''.join(buffer)))
                buffer = []
            in_wildcard = False
        else:
            buffer.append(char)

    if buffer:
        parts.append(('fixed', ''.join(buffer)))

    if in_wildcard:
        raise ValueError("Unmatched opening wildcard bracket.")
  • 初始化

    • parts 列表用于存储模板的各个部分。
    • buffer 用于缓存当前字符。
    • in_wildcard 标记当前是否在通配符中。
  • 遍历模板字符串

    • 如果遇到 {,检查是否已经在通配符中,如果是则抛出异常。否则,将 buffer 中的固定部分添加到 parts 中,并清空 buffer,设置 in_wildcard 为 True
    • 如果遇到 },检查是否在通配符中,如果不是则抛出异常。否则,将 buffer 中的通配符部分添加到 parts 中,并清空 buffer,设置 in_wildcard 为 False
    • 如果遇到其他字符,将其添加到 buffer 中。
  • 处理剩余字符

    • 最后检查 buffer 是否有剩余字符,如果有则将其作为固定部分添加到 parts 中。
    • 检查 in_wildcard 是否为 True,如果是则抛出异常。
匹配标题
    # 匹配标题
    def match(parts, title):
        i = 0
        for part_type, part in parts:
            if part_type == 'fixed':
                if title.startswith(part, i):
                    i += len(part)
                else:
                    return False
            elif part_type == 'wildcard':
                # 通配符可以匹配任意长度的字符串
                j = i
                while j <= len(title):
                    if match(parts[1:], title[j:]):
                        return True
                    j += 1
                return False
        return i == len(title)
  • 初始化索引

    • i 初始化为0,表示当前匹配的位置。
  • 遍历 parts 列表

    • 如果当前部分是固定部分,检查 title 是否以该固定部分开头,如果是则移动索引 i,否则返回 False
    • 如果当前部分是通配符部分,尝试匹配任意长度的字符串,递归检查剩余部分。如果匹配成功则返回 True,否则继续尝试。
  • 检查匹配结果

    • 最后检查索引 i 是否等于 title 的长度,如果是则返回 True,否则返回 False
主函数
def solution(n, template, titles):
    results = []
    for title in titles:
        results.append(is_generated_from_template(template, title))
    return ",".join("True" if result else "False" for result in results)
  • 初始化结果列表

    • results 列表用于存储每个标题的匹配结果。
  • 遍历标题

    • 对每个标题调用 is_generated_from_template 函数,将结果添加到 results 列表中。
  • 返回结果

    • 将 results 列表中的布尔值转换为字符串,并用逗号连接成一个字符串返回。

测试用例解析

测试用例1

输入template = "ad{xyz}cdc{y}f{x}e", titles = ["adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"]

  1. 提取模板部分

    • parts = [('fixed', 'ad'), ('wildcard', 'xyz'), ('fixed', 'cdc'), ('wildcard', 'y'), ('fixed', 'f'), ('wildcard', 'x'), ('fixed', 'e')]
  2. 匹配标题

    • "adcdcefdfeffe":匹配成功。
    • "adcdcefdfeff":匹配失败。
    • "dcdcefdfeffe":匹配失败。
    • "adcdcfe":匹配成功。
  3. 结果"True,False,False,True"

测试用例2

输入template = "{xxx}h{cQ}N{vF}u{XTA}S{NTA}MLCq{yyy}", titles = ["CLSomGhcQNvFuzENTAMLCqxBdj", "CLSomNvFuXTASzENTAMLCqxBdj", "CLSomFuXTASzExBdj", "CLSoQNvFuMLCqxBdj", "SovFuXTASzENTAMLCq", "mGhcQNvFuXTASzENTAMLCqx"]

  1. 提取模板部分

    • parts = [('wildcard', 'xxx'), ('fixed', 'h'), ('wildcard', 'cQ'), ('fixed', 'N'), ('wildcard', 'vF'), ('fixed', 'u'), ('wildcard', 'XTA'), ('fixed', 'S'), ('wildcard', 'NTA'), ('fixed', 'MLCq'), ('wildcard', 'yyy')]
  2. 匹配标题

    • "CLSomGhcQNvFuzENTAMLCqxBdj":匹配失败。
    • "CLSomNvFuXTASzENTAMLCqxBdj":匹配失败。
    • "CLSomFuXTASzExBdj":匹配失败。
    • "CLSoQNvFuMLCqxBdj":匹配失败。
    • "SovFuXTASzENTAMLCq":匹配失败。
    • "mGhcQNvFuXTASzENTAMLCqx":匹配成功。
  3. 结果"False,False,False,False,False,True"

测试用例3

输入template = "a{bdc}efg", titles = ["abcdefg", "abefg", "efg"]

  1. 提取模板部分

    • parts = [('fixed', 'a'), ('wildcard', 'bdc'), ('fixed', 'efg')]
  2. 匹配标题

    • "abcdefg":匹配成功。
    • "abefg":匹配成功。
    • "efg":匹配失败。
  3. 结果"True,True,False"