一,题目详情
1,问题描述
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 bidword 对创意中的通配符(通配符是用成对 {} 括起来的字符串,可以包含 0 个或者多个字符)进行替换,用来提升广告投放体验。例如:“{末日血战} 上线送 SSR 英雄,三天集齐无敌阵容!”,会被替换成“帝国时代游戏下载上线送 SSR 英雄,三天集齐无敌阵容!”。给定一个含有通配符的创意和n个标题,判断这句标题是否从该创意替换生成的。
2,测试样例
样例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. 问题分析
我们需要判断给定的标题是否是由模板中的通配符替换生成的。模板中的通配符是用成对的 {} 括起来的字符串,可以匹配任意长度的字符(包括空字符串)。我们需要将模板转换为正则表达式模式,然后使用正则表达式匹配每个标题。
2. 详细分析
-
模板转换:
- 将模板中的通配符
{...}替换为正则表达式的匹配模式(.*?),表示匹配任意长度的字符。 - 普通字符需要转义,以确保它们在正则表达式中被正确匹配。
- 将模板中的通配符
-
正则表达式匹配:
- 使用
re.fullmatch函数来判断每个标题是否完全匹配转换后的正则表达式模式。
- 使用
三、代码实现
import re
def solution(n, template_, titles):
# 将模板里的通配符替换为匹配的正则表达式
regex_pattern = "^" # 开始匹配
i = 0
while i < len(template_):
if template_[i] == '{':
# 找到通配符的开始
j = i
while j < len(template_) and template_[j] != '}':
j += 1
# 提取通配符并跳过它
if j < len(template_):
regex_pattern += "(.*?)" # 通配符匹配任意字符
i = j + 1
else:
raise ValueError("Malformed template: unbalanced '{'.")
else:
# 普通字符的匹配
regex_pattern += re.escape(template_[i]) # 转义特殊字符
i += 1
regex_pattern += "$" # 结束匹配
# 结果判定
result = []
for title in titles:
if re.fullmatch(regex_pattern, title):
result.append("True")
else:
result.append("False")
return ",".join(result)
if __name__ == "__main__":
# 测试样例
print(solution(4, "ad{xyz}cdc{y}f{x}e", ["adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"])) # "True,False,False,True"
print(solution(3, "a{bdc}efg", ["abcdefg", "abefg", "efg"])) # "True,True,False"
print(solution(5, "{abc}xyz{def}", ["xyzdef", "abcdef", "abxyzdef", "xyz", "abxyz"])) # "True,False,True,True,True"
四、逐步推演(以样例1为例)
输入:
n = 4
template = "ad{xyz}cdc{y}f{x}e"
titles = ["adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"]
推演过程如下:
| 步骤 | 操作 | 结果 |
|---|---|---|
| 1 | 转换模板为正则表达式模式 | ^ad(.*?)cdc(.*?)f(.*?)e$ |
| 2 | 匹配第一个标题 "adcdcefdfeffe" | 完全匹配,结果为 True |
| 3 | 匹配第二个标题 "adcdcefdfeff" | 不匹配,结果为 False |
| 4 | 匹配第三个标题 "dcdcefdfeffe" | 不匹配,结果为 False |
| 5 | 匹配第四个标题 "adcdcfe" | 完全匹配,结果为 True |
最终结果为 "True,False,False,True",与预期一致。
五、复杂度分析
-
时间复杂度:O(n)
- 转换模板为正则表达式模式的时间复杂度为 O(m),其中 m 是模板的长度。
- 每个标题的匹配时间复杂度为 O(k),其中 k 是标题的长度。
- 总体时间复杂度为 O(n * k + m)。
-
空间复杂度:O(1)
- 仅使用常数级额外空间。
六、总结
通过将模板转换为正则表达式模式并使用正则表达式匹配,我们实现了一个高效且简洁的解决方案。该算法具有以下特点:
- 高效性:时间复杂度为 O(n * k + m),适用于大多数场景。
- 鲁棒性:能够处理多种输入情况,包括复杂的通配符匹配。
- 易读性:代码逻辑清晰,易于理解和维护。
这种解法不仅适用于本题,还可以广泛应用于类似的字符串匹配问题中。