问题描述
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 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"
代码解析:
这段代码的主要功能是判断给定的标题列表是否与模板匹配。模板中可以使用 {...} 表示通配符,可以匹配任意长度的字符串(包括空字符串)。
代码的核心逻辑在于 match_template 函数中的 backtrack 递归函数。该函数通过回溯法遍历模板和标题的所有可能匹配情况,并判断是否能够完全匹配。
代码注释:
代码中已经添加了详细的注释,解释了每个函数和代码块的功能、参数和返回值,以及关键的逻辑判断。
主要步骤:
-
遍历标题列表: 代码首先遍历
titles列表中的每个标题。 -
匹配模板: 对于每个标题,调用
match_template函数判断其是否与模板匹配。 -
回溯匹配:
match_template函数中使用backtrack递归函数进行回溯匹配。- 基本情况: 如果模板和标题都到达末尾,则匹配成功。如果模板到达末尾但标题没有匹配完,或标题到达末尾但模板未匹配完,则匹配失败。
- 通配符匹配: 如果遇到
{,则寻找匹配的},并跳过{...}内的内容。然后,尝试将通配符与标题中任意长度的字符串进行匹配,并递归判断剩余部分是否匹配。 - 普通字符匹配: 如果当前字符不是
{,则将其与标题中的对应字符进行比较。如果匹配,则继续递归匹配下一个字符;否则,匹配失败。
-
记录结果: 将每个标题的匹配结果存储在
results列表中。 -
返回结果: 将
results列表转换为逗号分隔的字符串并返回。
示例:
例如,对于模板 "a{bdc}efg" 和标题 "abcdefg",backtrack 函数的执行过程如下:
- 初始状态:
i = 0,j = 0。 - 匹配
a:template[0] == title[0],i和j分别加 1。 - 遇到
{:寻找},i变为 5。 - 通配符匹配:尝试将
"{bdc}"与"bcdef"、"cdef"、"def"、"ef"、"f"和""进行匹配。 - 递归匹配:当
"{bdc}"匹配"bcd"时,递归调用backtrack(5, 3),继续匹配剩余部分。 - 最终匹配成功:
i和j都到达末尾。
def solution(n, template_, titles):
'''
这个函数用于判断多个标题是否与给定的模板匹配。
参数:
n: 标题的数量 (int)
template_: 模板字符串 (str)
titles: 标题列表 (list of str)
返回值:
一个逗号分隔的字符串,表示每个标题是否与模板匹配 (str)
例如: "True,False,True"
'''
def match_template(template, title):
'''
这个函数使用回溯法判断单个标题是否与模板匹配。
参数:
template: 模板字符串 (str)
title: 标题字符串 (str)
返回值:
如果标题与模板匹配,则返回 True,否则返回 False (bool)
'''
def backtrack(i, j):
'''
这是一个递归函数,用于在模板和标题中进行回溯匹配。
参数:
i: 当前在模板字符串中的索引 (int)
j: 当前在标题字符串中的索引 (int)
返回值:
如果从当前索引开始可以匹配成功,则返回 True,否则返回 False (bool)
'''
# 如果模板和标题都到达末尾,则匹配成功
if i == len(template) and j == len(title):
return True
# 如果模板到达末尾但标题没有匹配完,或标题到达末尾但模板未匹配完,则匹配失败
if i == len(template) or j > len(title): # 注意这里 j > len(title) 是允许的,因为通配符可以匹配空字符串
return False
# 如果遇到 '{',则寻找匹配的 '}'
if template[i] == '{':
end = i + 1
while end < len(template) and template[end] != '}':
end += 1
# 获取 `{...}` 内的内容并跳过
i = end + 1
# 通配符匹配标题中任意长度的字符串
for k in range(j, len(title) + 1): # 注意 k 可以取到 len(title),表示匹配空字符串
if backtrack(i, k): # 递归判断从 k 开始匹配
return True
return False # 如果所有可能的 k 都无法匹配,则返回 False
else:
# 普通字符精确匹配
if j < len(title) and template[i] == title[j]:
return backtrack(i + 1, j + 1)
return False # 如果当前字符不匹配,则返回 False
return backtrack(0, 0) # 从模板和标题的开头开始匹配
results = []
for title in titles:
if match_template(template_, title):
results.append("True")
else:
results.append("False")
return ",".join(results) # 将结果转换为逗号分隔的字符串
# 测试代码
if __name__ == "__main__":
testTitles1 = ["adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"]
testTitles2 = ["abcdefg", "abefg", "efg"]
testTitles3 = ["xyzdef", "abcdef", "abxyzdef", "xyz", "abxyz"]
print(solution(4, "ad{xyz}cdc{y}f{x}e", testTitles1)) # Expected: "True,False,False,True"
print(solution(3, "a{bdc}efg", testTitles2)) # Expected: "True,True,False"
print(solution(5, "{abc}xyz{def}", testTitles3)) # Expected: "True,False,True,True,True"