创意标题匹配问题
问题描述
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 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"
解题思路
这是一个关于字符串匹配和通配符处理的问题。核心思路是对给定的含有通配符的创意模板与每个标题进行比较,检查标题是否能通过创意模板中的通配符替换得到。
-
通配符处理
- 通配符用成对的
{}表示,可以包含任意字符。在比较过程中,需要跳过通配符部分进行字符的匹配。
- 通配符用成对的
-
逐个比较
- 对于每个标题,按照从左到右的顺序与创意模板进行比较。当遇到创意模板中的通配符时,在标题中对应的位置应该有相应的字符序列(可能为空),并且后续的非通配符字符也应该匹配。
步骤分析
-
解析创意模板
- 首先,需要对创意模板进行解析,标记出通配符的位置和内容。可以通过遍历创意模板字符串,当遇到
{时,记录通配符开始位置,当遇到}时,记录通配符结束位置,从而确定通配符部分。
- 首先,需要对创意模板进行解析,标记出通配符的位置和内容。可以通过遍历创意模板字符串,当遇到
-
标题比较
- 对于每个标题,设置两个指针,一个指向创意模板,一个指向标题。
- 当创意模板指针指向非通配符字符时,比较创意模板和标题中对应位置的字符是否相同。如果不同,则该标题不符合要求。
- 当创意模板指针指向通配符时,在标题中跳过相应长度的字符(通配符内的字符长度可以为0),然后继续比较后续的字符。
-
结果记录
- 根据每个标题与创意模板的比较结果,生成相应的布尔值结果,最后将这些布尔值转换为题目要求的字符串形式(
True或False连接成的字符串)。
- 根据每个标题与创意模板的比较结果,生成相应的布尔值结果,最后将这些布尔值转换为题目要求的字符串形式(
代码实现
以下是基于上述思路的C++实现代码:
#include <iostream>
#include <string>
#include <vector>
std::string check_titles(int n, const std::string& templateStr, const std::vector<std::string>& titles) {
std::vector<std::string> results;
for (const auto& title : titles) {
int template_ptr = 0;
int title_ptr = 0;
while (template_ptr < templateStr.length() && title_ptr < title.length()) {
if (templateStr[template_ptr] == '{') {
int end = templateStr.find('}', template_ptr);
template_ptr = end + 1; }
else if (templateStr[template_ptr]!= title[title_ptr]) {
break;
} else
{ template_ptr++; title_ptr++;
}
}
if (template_ptr == templateStr.length() && title_ptr == title.length()) { results.push_back("True");
} else {
results.push_back("False");
}
}
std::string resultStr = "";
for (size_t i = 0; i < results.size(); i++) {
if (i!= 0) {
resultStr += ",";
}
resultStr += results[i];
}
return resultStr;
}
-
函数定义与参数接收
- 定义函数
check_titles,它接受一个整数n(与题目输入格式一致,在函数内部未实际用于计算)、一个常量引用的字符串templateStr(创意模板)和一个常量引用的字符串向量titles(标题列表)。
- 定义函数
-
结果向量初始化与标题遍历
- 创建一个空的字符串向量
results来存储每个标题的比较结果。 - 使用范围
for循环遍历titles中的每个标题。对于每个标题,初始化两个指针template_ptr和title_ptr,分别用于指向创意模板和标题的当前字符位置。
- 创建一个空的字符串向量
-
比较逻辑
-
在
while循环中,只要template_ptr小于创意模板的长度并且title_ptr小于标题的长度,就进行比较。- 如果创意模板的当前字符是
{,则找到对应的}的位置,并将template_ptr移动到}之后的位置。 - 如果创意模板的当前字符与标题的当前字符不相同,则跳出
while循环。 - 如果相同,则将两个指针都向后移动一位。
- 如果创意模板的当前字符是
-
-
结果判断与添加到结果向量
- 当
while循环结束后,如果template_ptr等于创意模板的长度并且title_ptr等于标题的长度,说明标题符合要求,将"True"添加到results向量中;否则,将"False"添加到results向量中。
- 当
-
构建最终结果字符串
- 创建一个空字符串
resultStr,然后遍历results向量。对于每个元素,如果不是第一个元素,则在前面添加一个逗号,然后将元素添加到resultStr中。
- 创建一个空字符串
-
结果返回
- 最后,返回构建好的
resultStr,它包含了所有标题的比较结果字符串。
- 最后,返回构建好的
时间复杂度和空间复杂度
-
时间复杂度
- 对于每个标题,在最坏情况下,需要遍历创意模板和标题的每个字符。假设创意模板的长度为
m,标题的平均长度为k,总共有n个标题。那么时间复杂度为O(n∗(m+k))O(n∗(m+k))
。
- 对于每个标题,在最坏情况下,需要遍历创意模板和标题的每个字符。假设创意模板的长度为
-
空间复杂度
- 除了结果列表
results,没有使用额外的与输入规模相关的空间。结果列表的长度取决于标题的数量n,所以空间复杂度为O(n)O(n)
。
- 除了结果列表
总结
通过对创意模板和标题的仔细分析与比较,我们可以有效地判断标题是否是从创意模板通过通配符替换得到的。这种方法在广告平台中对于准确投放广告、提升广告投放体验有着重要的意义。