字节MarsCode题集

172 阅读3分钟

问题描述

在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 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方法

核心函数

  1. solution: 主函数,用于处理整个逻辑。
  2. template_to_regex: 将创意模板转换为正则表达式。
  3. 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"));
    }