问题描述
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 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
解题思路
目标是判断给定的标题是否可以通过含有通配符{}的模板,故应采用正则表达式来匹配。
大致思路为:
将模板转成非贪婪的正则表达式,再将其与字符串进行匹配,此处调用
python : re.fullmatch
对应java : String类的matches方法
核心函数
solution: 主函数,用于处理整个逻辑。template_to_regex: 将创意模板转换为正则表达式。find_closing_brace: 辅助函数,用于找到匹配的闭合括号。
1. solution 函数
- 正则表达式生成:调用
template_to_regex函数,将创意模板转换为正则表达式。 - 匹配检查:遍历每个标题,使用
re.fullmatch检查它是否与正则表达式完全匹配。
2. template_to_regex 函数
将模板转换为正则表达式,步骤:
- 初始化:创建一个空字符串
regex,用于构建正则表达式。 - 遍历模板:逐个字符遍历模板字符串。
- 处理通配符:如果遇到
{,调用find_closing_brace函数找到匹配的},并将之间的内容替换为(.*?)(非贪婪匹配)。 - 转义特殊字符:使用
re.escape对非通配符字符进行转义,以确保它们在正则表达式中被视为普通字符。
3. find_closing_brace 函数
找前括号对应的后括号位置:
- 计数器:使用
brace_count计数器跟踪括号的匹配。 - 遍历查找:从
{的索引开始匹配,直到找到匹配的},括号计数-1,并返回}索引
Python 版本
Java版本
import java.util.regex.Pattern;
public class Main {
public static String solution(int n, String template, String[] titles) {
StringBuilder results = new StringBuilder();
for (String title : titles) {
if (matchByReg(title, template)) {
results.append("True");
} else {
results.append("False");
}
results.append(",");
}
// Remove the last comma
if (results.length() > 0) {
results.setLength(results.length() - 1);
}
return results.toString();
}
public static boolean matchByReg(String s, String p) {
StringBuffer reg = new StringBuffer();
for (int i = 0; i < p.length(); i++) {
if (p.charAt(i) == '{') {
int endIdx = findClosingBrace(p, i);
reg.append("(.*?)");
i = endIdx;
} else {
reg.append(Pattern.quote(String.valueOf(p.charAt(i))));
}
}
return s.matches("^" + reg.toString() + "$");
}
private static int findClosingBrace(String s, int openIdx) {
int closeIdx = openIdx;
int braceCount = 1;
while (braceCount > 0) {
closeIdx++;
if (s.charAt(closeIdx) == '}') {
braceCount--;
}
}
return closeIdx;
}
public static void main(String[] args) {
// You can add more test cases here
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).toString().equals("True,True,False"));
}