1.创意标题匹配问题
问题描述
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 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"
2.解题思路
这个问题的核心在于如何将包含 {} 的模板转化为可以用于正则表达式匹配的形式,并检查每个标题是否符合这个模板。
分析
-
模板转化为正则表达式:
{}是一个通配符,代表一个可以匹配零个或多个字符。因此,我们需要将模板中的每个{}替换为正则表达式中的.*,这可以匹配任意长度的字符。需要注意的是,
{}可能包含字母、数字或者其他字符,所有这些字符都应该视作正常字符而不是正则表达式的特殊字符,所以我们需要正确处理这些内容。 -
正则表达式的构造:
在模板中,
{}可以包裹任意字符,因此,{}之间的内容都可以通过.*来表示。完整的正则表达式需要以
^开头和$结尾,这样可以确保整个字符串与模板严格匹配。 -
匹配过程:
通过构造正则表达式后,我们就可以使用正则表达式匹配每个标题。
对于每个标题,如果能够完全匹配正则表达式,说明这个标题符合模板,返回
True;否则,返回False。
步骤
-
将模板转换为正则表达式:
替换所有的
{}为.*。添加正则表达式的开始和结束符号
^和$,保证匹配的是完整字符串。 -
匹配标题:
对于每一个标题,使用转换后的正则表达式进行匹配。
-
输出结果:
对每个标题,输出
True或False,并按逗号分隔。
3.代码实现
import java.util.regex.*;
public class Main {
public static String solution(int n, String template_, String[] titles) {
// 替换模板中的通配符为正则表达式
String regex = template_.replaceAll("\\{[^}]*\\}", ".*");
// 加上开始和结束标记
regex = "^" + regex + "$";
Pattern pattern = Pattern.compile(regex);
StringBuilder result = new StringBuilder();
for (int i = 0; i < n; i++) {
Matcher matcher = pattern.matcher(titles[i]);
if (matcher.matches()) {
result.append("Tarue");
} else {
result.append("False");
}
if (i < n - 1) {
result.append(",");
}
}
return result.toString();
}
public static void main(String[] args) {
String[] testTitles1 = {"adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"};
String[] testTitles2 = {"CLSomGhcQNvFuzENTAMLCqxBdj", "CLSomNvFuXTASzENTAMLCqxBdj", "CLSomFuXTASzExBdj", "CLSoQNvFuMLCqxBdj", "SovFuXTASzENTAMLCq", "mGhcQNvFuXTASzENTAMLCqx"};
String[] testTitles3 = {"abcdefg", "abefg", "efg"};
System.out.println(solution(4, "ad{xyz}cdc{y}f{x}e", testTitles1).equals("True,False,False,True"));
System.out.println(solution(6, "{xxx}h{cQ}N{vF}u{XTA}S{NTA}MLCq{yyy}", testTitles2).equals("False,False,False,False,False,True"));
System.out.println(solution(3, "a{bdc}efg", testTitles3).equals("True,True,False"));
}
}
-
template_的处理:- 使用
replaceAll("\{[^}]*\}", ".*")将模板中的所有{}转换为.*。[^}]*用于匹配{}内的所有字符,包括字母、数字和特殊字符。 ^和$用于确保整个字符串从头到尾完全匹配。
- 使用
-
匹配过程:
- 使用
Pattern.compile(regex)将转换后的正则表达式编译成Pattern对象。 - 使用
matcher.matches()来检查每个标题是否完全匹配正则表达式。
- 使用
-
结果构建:
- 将每个匹配结果(
True或False)拼接到StringBuilder中,多个结果之间用逗号分隔。
- 将每个匹配结果(
4.时间复杂度
- 时间复杂度:每个标题进行一次正则匹配,匹配的时间复杂度为 O(m),其中 m 是标题的长度。对于 n 个标题,总时间复杂度是 O(n * m)。
- 空间复杂度:主要是用来存储正则表达式和结果的空间,空间复杂度为 O(n),其中 n 是标题的数量。