每日一题:创意标题匹配问题(青训营X豆包MarsCode) | 豆包MarsCode AI 刷题

147 阅读3分钟

问题描述

在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 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. 模板转换为正则表达式

  • 目标:将含有通配符的模板转换成一个正则表达式,以便后续的匹配操作。

  • 步骤

    1. 转义特殊字符:模板中可能包含正则表达式中的特殊字符(如 ., *, ?, {, }, [, ] 等)进行转义,通过函数escape实现。
    2. 替换通配符:将模板中的每个通配符 {...} 替换为正则表达式的 .*?,表示它可以匹配任意长度的任意字符(非贪婪匹配)。通过函数sub实现。

2. 匹配标题

  • 目标:使用生成的正则表达式来匹配每个给定的标题,判断其是否符合模板。

  • 步骤

    1. 编译正则表达式:使用 re.compile 编译生成的正则表达式。
    2. 全匹配:使用 re.fullmatch 方法来检查每个标题是否完全符合正则表达式。
    3. 记录结果:将每个标题的匹配结果(True 或 False)记录下来。

3. 返回结果

  • 目标:将所有标题的匹配结果以逗号分隔的字符串形式返回。

  • 步骤

    1. 拼接结果:将所有匹配结果(True 或 False)拼接成一个逗号分隔的字符串。
    2. 返回结果:返回拼接好的字符串。

详细实现

import re

def solution(n, template_, titles):
    # Step 1: 将模板转换为正则表达式
    # 1.1 转义模板中的特殊字符
    regex = re.escape(template_)
    # 1.2 替换模板中的通配符 {.*?} 为正则表达式的 .*
    regex = re.sub(r'\\{.*?\\}', '.*?', regex)
    
    # Step 2: 编译正则表达式
    pattern = re.compile(regex)
    
    # Step 3: 匹配每个标题
    results = []
    for title in titles:
        if pattern.fullmatch(title):
            results.append("True")
        else:
            results.append("False")
    
    # Step 4: 返回结果
    return ",".join(results)

if __name__ == "__main__":
    testTitles1 = ["adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"]
    testTitles2 = ["CLSomGhcQNvFuzENTAMLCqxBdj", "CLSomNvFuXTASzENTAMLCqxBdj", "CLSomFuXTASzExBdj", "CLSoQNvFuMLCqxBdj", "SovFuXTASzENTAMLCq", "mGhcQNvFuXTASzENTAMLCqx"]
    testTitles3 = ["abcdefg", "abefg", "efg"]

    print(solution(4, "ad{xyz}cdc{y}f{x}e", testTitles1) == "True,False,False,True" )
    print(solution(6, "{xxx}h{cQ}N{vF}u{XTA}S{NTA}MLCq{yyy}", testTitles2) == "False,False,False,False,False,True" )
    print(solution(3, "a{bdc}efg", testTitles3) == "True,True,False" )

代码解释

  1. 模板转换为正则表达式

    • re.escape(template_):将模板中的所有特殊字符转义。
    • re.sub(r'\{.*?\}', '.*?', regex):将模板中的 {...} 通配符替换为 .*?,表示它可以匹配任意长度的任意字符(非贪婪匹配)。
  2. 编译正则表达式

    • pattern = re.compile(regex):编译生成的正则表达式,以便后续的匹配操作。
  3. 匹配每个标题

    • pattern.fullmatch(title):使用 fullmatch 方法检查每个标题是否完全符合正则表达式。
    • 根据匹配结果,将 TrueFalse 添加到结果列表中。
  4. 返回结果

    • ",".join(results):将结果列表中的所有元素拼接成一个逗号分隔的字符串。

心得体会

对于正则表达式的相关函数不是特别熟悉,但是通过询问豆包MarsCode可以得到特别详细的函数推荐以及解释,刷题的体验很不错。同时对于编辑器代码检查的功能能够帮助快速定位到问题代码所在的行数,非常高效。