创意标题匹配问题|豆包MarsCode AI刷题

89 阅读5分钟

一、问题描述

在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 bidword 对创意中的通配符(通配符是用成对 {} 括起来的字符串,可以包含 0 个或者多个字符)进行替换,用来提升广告投放体验。例如:“{末日血战} 上线送 SSR 英雄,三天集齐无敌阵容!”,会被替换成“帝国时代游戏下载上线送 SSR 英雄,三天集齐无敌阵容!”。给定一个含有通配符的创意和n个标题,判断这句标题是否从该创意替换生成的。


测试样例

样例:

输入:n = 4, template = "ad{xyz}cdc{y}f{x}e", titles = ["adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"]
输出:"True,False,False,True"

二、思路分析

步骤一:提取创意中的通配符和固定文本

  1. 扫描创意字符串:遍历创意字符串,找到所有成对的 { 和 } 之间的内容,这些是通配符部分。
  2. 分割固定文本:将创意字符串分割成多个片段,这些片段是由通配符分隔开的固定文本。

例如,对于创意 "{末日血战} 上线送 SSR 英雄,三天集齐无敌阵容!",我们可以提取出两个通配符 "末日血战" 和 "帝国时代游戏下载",以及三个固定文本片段:["", " 上线送 SSR 英雄,三天集齐无敌阵容!"]。

步骤二:构建状态机进行匹配

  1. 初始化状态机:创建一个状态机,初始状态为第一个固定文本片段。
  2. 遍历标题字符串:逐字符遍历标题字符串,根据当前字符与固定文本片段的匹配情况更新状态机的状态。
  3. 处理通配符:当遇到通配符时,检查当前状态是否允许进入通配符状态,并记录需要匹配的通配符位置。
  4. 匹配固定文本:在非通配符区域,直接匹配固定文本片段。
  5. 回溯机制:如果在某个状态下匹配失败,尝试回溯到上一个状态,继续匹配其他可能的路径。

步骤三:判断匹配结果

  1. 完全匹配:如果状态机能够成功地从初始状态到达最终状态,并且所有固定文本片段都得到了匹配,则认为标题是通过替换创意生成的。
  2. 部分匹配或不匹配:如果在任何时候匹配失败,或者有未匹配的固定文本片段,则认为标题不是通过替换创意生成的。

三、代码

public class Main {
    public static String solution(int n, String template_, String[] titles) {
        String regexPattern = template_.replaceAll("\\{[^{}]*\\}", "(.*)");
        Pattern pattern = Pattern.compile(regexPattern);
        StringBuilder result = new StringBuilder();
        for (String title : titles) {
            Matcher matcher = pattern.matcher(title);
            if (matcher.matches()) {
                result.append("True,");
            } else {
                result.append("False,");
            }
        }
        return result.substring(0, result.length() - 1);
    }
    public static void main(String[] args) {
        // Test cases
        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"));
    }
}

核心思想

1、模板转换:将模板中的每个通配符(例如 {xyz})替换为正则表达式中的捕获组 (.*)。这样,模板中的所有通配符都可以匹配任意字符序列。

2、编译正则表达式:将生成的正则表达式字符串编译成一个 Pattern 对象,以便后续进行匹配操作。

3、匹配标题:遍历每个标题,使用 Matcher 对象检查标题是否完全匹配正则表达式。如果匹配,结果为 True,否则为 False

4、返回结果:去掉结果字符串末尾的逗号并返回

四、总结

本题的核心是判断一个给定的标题是否可以通过替换创意中的通配符生成。通配符用成对的花括号 {} 括起来,可以包含0个或多个字符。我们需要设计一个算法来验证标题的生成过程是否符合创意中定义的模式。

关键步骤:

  1. 提取通配符和固定文本:从创意中提取出所有的通配符和固定文本片段。这些片段将用于构建状态机进行匹配。
  2. 构建状态机进行匹配:通过遍历标题字符串,利用状态机模拟标题的生成过程。状态机的状态由当前匹配到的固定文本片段决定,当遇到通配符时,进入特殊处理逻辑。
  3. 回溯机制:在匹配过程中,如果当前路径失败,尝试回溯到上一个状态,继续匹配其他可能的路径。
  4. 最终判断:如果状态机能够成功地从初始状态到达最终状态,并且所有固定文本片段都得到了匹配,则认为标题是通过替换创意生成的。

算法复杂度分析:

  • 时间复杂度:主要取决于标题的长度和创意中通配符及固定文本的数量。在最坏情况下,可能需要遍历标题的每个字符并进行多次回溯,因此时间复杂度较高。
  • 空间复杂度:主要用于存储提取的通配符和固定文本片段,以及状态机的状态信息。空间复杂度相对较低。