问题描述
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 bidword 对创意中的通配符(通配符是用成对 {} 括起来的字符串,可以包含 0 个或者多个字符)进行替换,用来提升广告投放体验。例如:“{末日血战} 上线送 SSR 英雄,三天集齐无敌阵容!”,会被替换成“帝国时代游戏下载上线送 SSR 英雄,三天集齐无敌阵容!”。给定一个含有通配符的创意和n个标题,判断这句标题是否从该创意替换生成的。
问题理解
需要判断给定的标题是否可以从一个包含通配符的模板中生成。通配符用 {} 括起来,可以匹配任意字符串(包括空字符串)。
数据结构选择
- 字符串处理:由于我们需要处理字符串的匹配,使用正则表达式是一个不错的选择。
- 正则表达式:我们可以将模板中的通配符部分转换为正则表达式的
.*,表示匹配任意字符(包括空字符串)。
算法步骤
- 解析模板:遍历模板字符串,将通配符部分替换为
.*,非通配符部分进行转义(防止特殊字符影响正则表达式的匹配)。 - 生成正则表达式:将解析后的模板字符串转换为正则表达式。
- 匹配标题:使用生成的正则表达式匹配每个标题,判断是否匹配成功。
- 返回结果:将匹配结果转换为逗号分隔的字符串返回。
具体步骤
- 遍历模板字符串:
- 如果遇到
{,则找到对应的},将这部分替换为.*。 - 如果遇到普通字符,则进行转义。
- 如果遇到
- 生成正则表达式:将处理后的模板字符串作为正则表达式的模式。
- 匹配标题:使用
re.match函数对每个标题进行匹配。 - 返回结果:将匹配结果列表转换为字符串返回。
代码分析
根据上面思路写出代码如下:
import re
def solution(n, template, titles):
# Please write your code here
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 列表转换为逗号分隔的字符串
results_str = ','.join(map(str, results))
return results_str
-
导入模块:
import re:导入了正则表达式模块,用于处理字符串匹配。
-
函数定义:
def solution(n, template, titles)::定义了一个函数solution,接受三个参数:n(标题数量)、template(模板字符串)、titles(标题列表)。
-
正则表达式生成:
regex_pattern = '':初始化正则表达式模式字符串。i = 0:初始化索引i,用于遍历模板字符串。while i < len(template)::遍历模板字符串。if template[i] == '{'::如果遇到{,则进入通配符处理逻辑。i += 1:跳过{。while i < len(template) and template[i] != '}'::找到对应的}。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列表中。
-
结果转换:
results_str = ','.join(map(str, results)):将results列表转换为逗号分隔的字符串。
-
返回结果:
return results_str:返回结果字符串。
-
测试用例:
if __name__ == "__main__"::主程序入口。- 定义了三个测试用例,并打印结果以验证代码的正确性。
改进建议
-
边界情况处理:
- 可以考虑添加更多的边界测试用例,例如模板中没有通配符、通配符在字符串的开头或结尾等情况。
-
代码可读性:
- 可以考虑将正则表达式的生成逻辑封装为一个单独的函数,以提高代码的可读性和可维护性。
-
性能优化:
- 当前代码的性能已经足够好,但如果标题数量非常大,可以考虑使用更高效的正则表达式引擎或优化匹配逻辑。
方法和算法
这道题的解答主要用到了以下方法和算法:
-
正则表达式(Regular Expressions):
- 用途:正则表达式用于匹配字符串的模式。在这个问题中,我们需要将模板中的通配符部分替换为可以匹配任意字符的正则表达式模式。
- 实现:使用 Python 的
re模块来处理正则表达式。
-
字符串处理:
- 用途:处理模板字符串,识别通配符并将其转换为正则表达式模式。
- 实现:遍历模板字符串,识别
{和}之间的通配符部分,并将其替换为.*,表示匹配任意字符(包括空字符串)。非通配符部分使用re.escape进行转义,以防止特殊字符影响正则表达式的匹配。
-
正则表达式编译:
- 用途:将生成的正则表达式模式编译为正则表达式对象,以便后续进行匹配。
- 实现:使用
re.compile函数将生成的正则表达式模式编译为正则表达式对象。
-
字符串匹配:
- 用途:使用编译好的正则表达式对象对每个标题进行匹配,判断标题是否符合模板生成的模式。
- 实现:使用
regex.match函数对每个标题进行匹配,并返回匹配结果。
-
列表处理:
- 用途:将匹配结果存储在列表中,并将列表转换为逗号分隔的字符串返回。
- 实现:使用列表推导式将匹配结果存储在
results列表中,然后使用join函数将列表转换为逗号分隔的字符串。
具体步骤
-
解析模板字符串:
- 遍历模板字符串,识别通配符部分并将其替换为
.*,非通配符部分进行转义。
- 遍历模板字符串,识别通配符部分并将其替换为
-
生成正则表达式:
- 将解析后的模板字符串编译为正则表达式对象。
-
匹配标题:
- 使用编译好的正则表达式对象对每个标题进行匹配,判断是否匹配成功。
-
返回结果:
- 将匹配结果列表转换为逗号分隔的字符串返回。
总结
这道题的解答主要用到了正则表达式、字符串处理、正则表达式编译、字符串匹配和列表处理等方法和算法。通过这些方法,我们可以有效地判断每个标题是否可以从模板生成。