问题描述
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 bidword 对创意中的通配符(通配符是用成对 {} 括起来的字符串,可以包含 0 个或者多个字符)进行替换 ,用来提升广告投放体验。例如:“{末日血战} 上线送 SSR 英雄,三天集齐无敌阵容!”,会被替换成“帝国时代游戏下载上线送 SSR 英雄,三天集齐无敌阵容!”。给定一个含有通配符的创意和一句标题,判断这句标题是否从该创意替换生成的。
输入格式
第一行输入为 N,代表有 N 个标题
第二行代表含有通配符的创意,创意中包含大小写英文字母和成对的花括号
第三行到第 N + 2 行,代表 N 句标题,每个标题只包含大小写英文字母
输出格式
N 行,每行为“True”或者“False”,判断该句标题是否符合创意
输入样例
4
ad{xyz}cdc{y}f{x}e
adcdcefdfeffe
adcdcefdfeff
dcdcefdfeffe
adcdcfe
输出样例
True
False
False
True
说明
adcdcefdfeffe 可以看作 ad{}cdc{efd}f{eff}e 或者 ad{}cdc{efdfe}f{f}e 替换生成,但是无论哪种替换方式都是符合该创意 ad{xyz}cdc{y}f{x}e。
数据范围
N <= 10
标题和创意的长度小于等于 100
难点在哪里?
-
通配符的处理:
- 创意中的通配符
{xyz}表示可以被任意内容替换。这意味着你要考虑到所有可能的替换组合,这使得匹配变得更加复杂。 - 通配符可以为空,也可以包含多个字符,这增加了匹配的不确定性。
- 创意中的通配符
-
如何将通配符替换成正则表达式:
- 因为
{xyz}可以替换为任何字符串,我们需要用正则表达式去描述这样的可能性。 - 使用正则表达式来处理字符串匹配可能会让一些同学感到陌生,特别是如何将特定的通配符替换为可以匹配任意字符的表达式。
- 因为
-
边界条件的处理:
- 创意模板和标题可能有不同的长度,因此在匹配时要考虑如何处理两者的差异,以及如何确保匹配从头到尾的严格性。
解题思路
为了判断一个标题是否符合创意模板中的通配符规则,我们可以将创意模板中的通配符部分替换为正则表达式的匹配符号,从而构建一个可以进行匹配的模式。
以下是解题的思路:
-
构造正则表达式:
- 首先,我们将创意模板中的通配符部分
{xyz}替换为正则表达式中的(.*),这意味着匹配任意长度的字符。 - 例如,模板
ad{xyz}cdc{y}f{x}e可以转换为正则表达式模式:ad(.*)cdc(.*)f(.*)e。其中(.*)表示任意字符的任意长度。
- 首先,我们将创意模板中的通配符部分
-
添加边界条件:
- 为了确保整个标题符合模板,而不是部分匹配,我们在正则表达式的开头和结尾添加
^和$。 - 这样可以保证从标题的开头匹配到结尾,确保整个标题符合要求。
- 为了确保整个标题符合模板,而不是部分匹配,我们在正则表达式的开头和结尾添加
-
逐个匹配标题:
- 使用 C++ 中的正则表达式库
<regex>,我们可以逐个匹配每个标题,判断它是否符合生成的正则表达式。 - 如果匹配成功,就返回
True,否则返回False。
- 使用 C++ 中的正则表达式库
代码的实现
具体来说,这里是代码的实现步骤:
-
正则表达式构建:
- 使用
std::regex_replace()将模板中的通配符{}替换为正则表达式的(.*),然后加上头尾的^和$,得到完整的匹配模式。
- 使用
-
匹配操作:
- 使用
std::regex构建正则表达式对象,然后用std::regex_match()对每个标题进行匹配。 - 匹配成功就加入结果字符串
True,否则加入False。
- 使用
-
去掉末尾逗号:
- 最后,拼接结果时为了格式美观,我们去掉最后多余的逗号。
举个例子
假如我们有一个创意模板:ad{xyz}cdc{y}f{x}e,和以下几个标题:
-
标题:
adcdcefdfeffe:- 我们将模板转换为正则表达式
ad(.*)cdc(.*)f(.*)e。 - 匹配的时候,可以看作
{xyz}是空字符串,{y}被替换为efd,{x}被替换为eff,所以匹配成功,返回True。
- 我们将模板转换为正则表达式
-
标题:
adcdcfe:{xyz}和{y}都被替换为空字符串,而{x}被替换为空,结果正好与adcdcfe一致,所以返回True。
-
标题:
adcdcefdfeff:- 这里匹配失败,因为
f后面多了一个f,无法匹配上模板。
- 这里匹配失败,因为
c
代码解读
复制代码
#include <bits/c++config.h>
#include <iostream>
#include <string>
#include <vector>
#include <regex>
std::string solution(int n, std::string titleTemplate, std::vector<std::string> titles) {
std::string result;
std::string pattern = titleTemplate;
pattern = std::regex_replace(pattern, std::regex("\{[^}]*\}"), "(.*)");
pattern = "^" + pattern + "$";
std::regex re(pattern);
for (const auto& title : titles) {
if (std::regex_match(title, re)) {
result += "True,";
} else {
result += "False,";
}
}
// Remove the trailing comma
if (!result.empty()) {
result.pop_back();
}
return result;
}
int main() {
std::vector<std::string> testTitles1 = {"adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"};
std::vector<std::string> testTitles2 = {"CLSomGhcQNvFuzENTAMLCqxBdj", "CLSomNvFuXTASzENTAMLCqxBdj", "CLSomFuXTASzExBdj", "CLSoQNvFuMLCqxBdj", "SovFuXTASzENTAMLCq", "mGhcQNvFuXTASzENTAMLCqx"};
std::vector<std::string> testTitles3 = {"abcdefg", "abefg", "efg"};
std::cout << (solution(4, "ad{xyz}cdc{y}f{x}e", testTitles1) == "True,False,False,True") << std::endl;
std::cout << (solution(6, "{xxx}h{cQ}N{vF}u{XTA}S{NTA}MLCq{yyy}", testTitles2) == "False,False,False,False,False,True") << std::endl;
std::cout << (solution(3, "a{bdc}efg", testTitles3) == "True,True,False") << std::endl;
return 0;
}