创意标题匹配问题| 豆包MarsCode AI 刷题

186 阅读4分钟

题目解析:创意标题匹配问题

在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 bidword 对创意中的通配符(通配符是用成对 {} 括起来的字符串,可以包含 0 个或者多个字符)进行替换,用来提升广告投放体验。例如:“{末日血战} 上线送 SSR 英雄,三天集齐无敌阵容!”,会被替换成“帝国时代游戏下载上线送 SSR 英雄,三天集齐无敌阵容!”。给定一个含有通配符的创意和n个标题,判断这句标题是否从该创意替换生成的。

测试样例

样例1:

输入:n = 4, template = "ad{xyz}cdc{y}f{x}e", titles = ["adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"]
输出:"True,False,False,True"

样例2:

输入:n = 3, template = "a{bdc}efg", titles = ["abcdefg", "abefg", "efg"]
输出:"True,True,False"

样例3:

输入:n = 5, template = "{abc}xyz{def}", titles = ["xyzdef", "abcdef", "abxyzdef", "xyz", "abxyz"]
输出:"True,False,True,True,True"

1. 输入参数

函数 solution(n, template, titles) 接受三个输入参数:

  • n:表示标题列表的长度(但在代码中并未直接使用,实际可以通过 len(titles) 代替)。
  • template:包含占位符的模板字符串。
  • titles:需要进行匹配的标题字符串列表。

2. 构建正则表达式

函数的核心工作是根据模板字符串 (template) 构造一个正则表达式,逐字符分析模板:

  • 遇到普通字符时,直接将其添加到正则表达式中,并确保非字母字符(如 .- 等)被转义,以避免与正则的特殊含义冲突。
  • 遇到占位符 {} 时,将其转换为 .*,表示匹配任意字符序列,.* 是正则表达式中的一个通配符,能够匹配任意数量的任意字符。

这部分的关键逻辑在于:

  • 使用 re.escape() 来确保模板中的普通字符在正则表达式中被正确转义(比如 { 和 })。
  • 遇到 {} 占位符时,通过 .* 来代替,使得对应部分可以匹配任意字符。

3. 匹配标题

构造出正则表达式后,接下来使用 re.compile(f'^{regex_pattern}$') 将模板字符串转换为一个完整的正则表达式。这里使用 ^$ 分别表示匹配字符串的开始和结束,确保正则表达式是对整个字符串进行全匹配。

然后,使用 regex.match(title) 对每一个标题 (title) 进行匹配。如果匹配成功,返回 True,否则返回 False。所有结果都收集到 results 列表中。

4. 返回结果

最终,将 results 列表中的布尔值(TrueFalse)转化为逗号分隔的字符串,并返回该字符串。例如:True,False,True

代码解析:

pythonCopy Code
import re

def solution(n, template, titles):
    # 初始化正则表达式的构造字符串
    regex_pattern = ''
    i = 0
    while i < len(template):
        if template[i] == '{':
            # 找到一个占位符的开始,查找匹配的结束 '}'
            i += 1
            while i < len(template) and template[i] != '}':
                i += 1
            # 将占位符 { ... } 转换为 .* 来匹配任意字符
            regex_pattern += '.*'
        else:
            # 对模板中的普通字符进行转义,并加入正则表达式
            regex_pattern += re.escape(template[i])
        i += 1

    # 构造完整的正则表达式,用 ^ 和 $ 来确保全匹配
    regex = re.compile(f'^{regex_pattern}$')

    # 对每个标题进行匹配
    results = [bool(regex.match(title)) for title in titles]

    # 将结果列表转化为逗号分隔的字符串
    results_str = ','.join(map(str, results))

    return results_str

测试案例

以下是对代码的几个测试案例及其分析:

测试案例1:

pythonCopy Code
testTitles1 = ["adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"]
solution(4, "ad{xyz}cdc{y}f{x}e", testTitles1)

模板为 "ad{xyz}cdc{y}f{x}e"

  • {xyz}{y}{x} 都是占位符,表示可以匹配任意字符。
  • 正则表达式会转换为:^ad.*cdc.*fe.*e$,意味着 ad 后跟任意字符、cdc 后跟任意字符、fe 后跟任意字符、以 e 结束。
  • 结果:True, False, False, True,匹配的标题为第1和第4个。

测试案例2:

pythonCopy Code
testTitles2 = ["CLSomGhcQNvFuzENTAMLCqxBdj", "CLSomNvFuXTASzENTAMLCqxBdj", "CLSomFuXTASzExBdj", "CLSoQNvFuMLCqxBdj", "SovFuXTASzENTAMLCq", "mGhcQNvFuXTASzENTAMLCqx"]
solution(6, "{xxx}h{cQ}N{vF}u{XTA}S{NTA}MLCq{yyy}", testTitles2)

模板为 "{xxx}h{cQ}N{vF}u{XTA}S{NTA}MLCq{yyy}"

  • 这是一个包含多个占位符的大模板,正则表达式会生成很长,但同样是通过 .* 来表示任意字符匹配。
  • 结果:False, False, False, False, False, True,只有最后一个标题符合模板。

测试案例3:

pythonCopy Code
testTitles3 = ["abcdefg", "abefg", "efg"]
solution(3, "a{bdc}efg", testTitles3)

模板为 "a{bdc}efg"

  • {bdc} 是一个占位符,允许匹配任意字符。
  • 正则表达式:^a.*efg$,匹配 a 后跟任意字符,再是 efg
  • 结果:True, True, False,前两个标题匹配,但第三个不匹配。

总结

这段代码通过构建一个正则表达式来模拟模板字符串的匹配过程。模板中的占位符 {} 被转换为正则表达式中的 .*,从而允许匹配任意字符。然后,逐个标题进行匹配,并返回布尔值的逗号分隔字符串。