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

62 阅读6分钟

问题简化

在广告平台中,广告主通过包含通配符的标题进行创意提交。这些通配符以大括号 {} 括起来,代表可以被任何内容替代。比如 {xyz} 可以被 "帝国时代" 替代。广告平台根据用户的搜索词替换这些通配符生成广告标题。

我们需要判断给定的一些标题,是否能通过替换给定模板中的通配符生成。若某个标题符合模板的替换规则,则返回 True,否则返回 False。多组标题需要分别判断,最终返回以逗号分隔的结果。

解题思路

  1. 模板与标题的匹配:
    • 模板中有 {} 括起来的通配符部分,表示可以匹配任意字符,可以为空,也可以是多个字符。
    • 把模板转换成一个正则表达式,用来匹配各个标题。对于模板中的每个通配符部分({}),可以使用正则表达式中的 .* 来匹配任意字符(包括空字符串)。
    • 对于模板中的非通配符部分,我们可以直接在正则表达式中使用其字面值。
  2. 正则表达式构建:
    • 在遍历模板的过程中,遇到 {} 时,将其替换为正则表达式中的 .*,表示匹配任意字符。
    • 非 {} 部分直接添加到正则表达式中。
    • 最终生成的正则表达式需要用 re.fullmatch() 来检查给定标题是否完全匹配。
  3. 多标题匹配:
    • 对于多个标题,逐个使用正则表达式进行匹配,收集结果并返回。

代码实现

以下是具体python代码实现

import re

def solution(n, template, titles):

导入了 Python 的 re 模块,并且定义了一个名为 solution 的函数,接收三个参数:

  • n: 模板字符串的长度
  • template: 一个字符串模板,包含了我们需要解析的模式,其中 {} 表示一个通配符,表示可以匹配任意字符(包括空字符)
  • titles: 一个字符串列表,包含多个标题,根据模板检查每个标题是否匹配
    regex_pattern = ''

初始化一个空字符串 regex_pattern,用来存储转换后的正则表达式。

    i = 0
    while i < len(template):

初始化 i = 0,然后使用 while 循环遍历模板 template 中的每个字符,直到遍历完整个模板。

        if template[i] == '{':

检查当前字符是否是 {。如果是 {,说明开始了一个通配符部分,接下来需要处理这个通配符。

            j = i + 1
            while j < len(template) and template[j] != '}':
                j += 1
  • 初始化 j = i + 1,即从 { 后开始搜索。
  • 使用一个内层 while 循环继续查找,直到遇到 } 或遍历到模板的末尾。这个循环的作用是找到匹配的 },因为 {} 是成对出现的。
            regex_pattern += '.*'

当找到匹配的 } 后,将 .*(正则表达式中的通配符,表示匹配任意字符)追加到 regex_pattern 中。这个操作表示将 {} 中的内容转换为正则表达式的 .*,即可以匹配任意字符(包括空字符)。

            i = j + 1

更新 i 的值,跳过处理完的 {} 部分,继续向后遍历模板。

        else:
            regex_pattern += re.escape(template[i])
            i += 1

如果当前字符不是 {,则表示它是普通字符。使用 re.escape() 函数将字符进行转义,以确保字符不会与正则表达式的特殊符号冲突(例如 .* 等)。然后将该转义后的字符添加到 regex_pattern 中,然后 i 加 1,继续向后遍历模板。

匹配标题的过程:

    result = []

初始化一个空列表 result,用来存储每个标题是否匹配模板的结果。

    for title in titles:
        if re.fullmatch(regex_pattern, title):
            result.append("True")
        else:
            result.append("False")
  • 遍历 titles 中的每个标题。
  • 使用 re.fullmatch(regex_pattern, title) 检查标题是否完全匹配正则表达式 regex_patternfullmatch() 方法会尝试将整个标题与正则表达式进行匹配,只有完全匹配时才会返回 True,否则返回 False
  • 如果匹配成功,将 "True" 添加到 result 列表,否则添加 "False"

返回结果:

    return ",".join(result)

使用 ",".join(result)result 列表中的每个元素连接成一个以逗号分隔的字符串,并返回这个字符串。

主程序的测试部分:(代码略)

总结

这道题目可以看作是一个关于正则表达式的应用题,要求将给定的模板字符串转换为正则表达式,并用这个正则表达式来匹配一组标题。 在具体实现的过程中,有几个小细节需要注意一下:

  • 字符转义:由于广告模板中可能存在一些特殊字符,所以,在构建正则表达式时,某些特殊字符(如 ., * 等)需要通过 re.escape() 进行转义,避免它们被错误地当作正则表达式的特殊符号处理。
  • {} 解析的配对:模板中如果存在 {},需要将它们正确地匹配,确保处理的是成对出现的花括号。如果没有正确匹配花括号,可能会导致程序逻辑错误。
  • 边界条件:本题要求完全匹配标题与模板,所以我们的正则表达式需要匹配整个字符串,而不是只匹配部分。为解决这个问题,我们使用 re.fullmatch() 来确保正则表达式完全匹配。

通过这道题,我更加深刻地理解了模板匹配的应用场景。在实际开发中,我们常常需要从某种模式或者规则中提取信息,而正则表达式是非常有效的工具之一。题目中的 {} 实际上是模板的占位符,类似于某些实际应用中需要处理的动态字段,学习如何将这些动态部分转化为正则表达式的能力,对于解决实际问题是很有帮助的。

补充

生成正则表达式的核心逻辑总结:

  • 对于每一个 {},将其转换为 .*
  • 对于普通字符,将其直接添加到正则表达式中,并确保特殊字符被转义。 最终,regex_pattern 将包含一个完整的正则表达式。

举个例子:

假设模板为 "ad{xyz}cdc{y}f{x}e",经过上述的转换后,正则表达式变成:

"ad.*cdc.*f.*e"

这个正则表达式表示:

  • ad 后跟任意字符(包括空字符),然后是 cdc,然后又是任意字符,再到 f,再是任意字符,最后是 e