题目解析:创意标题匹配问题
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 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 列表中的布尔值(True 或 False)转化为逗号分隔的字符串,并返回该字符串。例如: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,前两个标题匹配,但第三个不匹配。
总结
这段代码通过构建一个正则表达式来模拟模板字符串的匹配过程。模板中的占位符 {} 被转换为正则表达式中的 .*,从而允许匹配任意字符。然后,逐个标题进行匹配,并返回布尔值的逗号分隔字符串。