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

142 阅读6分钟

问题描述

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

题目描述

我们需要编写一个函数来匹配模板字符串和标题字符串。模板字符串包含固定部分和占位符,固定部分必须按顺序出现在标题中。根据模板的不同情况,有以下两种特殊要求:

  1. 如果模板的开头和结尾没有占位符,固定部分必须分别匹配标题的开头和结尾。
  2. 如果模板的开头和结尾有占位符,固定部分只需按顺序出现在标题中即可。

解决方案

我们将问题分解为以下步骤:

  1. 解析模板:提取模板中的固定部分。
  2. 检查占位符:判断模板是否以占位符开头或结尾。
  3. 匹配标题:根据固定部分和占位符的情况,匹配标题字符串。

代码实现

步骤1:解析模板

我们首先解析模板,提取其中的固定部分。占位符部分用 {} 包围,我们只需要提取固定部分。

python

def parse_template(template):
    fixed_parts = []
    i = 0
    while i < len(template):
        if template[i] == '{':
            while i < len(template) and template[i] != '}':
                i += 1
            i += 1  # Skip the closing '}'
        else:
            start = i
            while i < len(template) and template[i] != '{':
                i += 1
            fixed_parts.append(template[start:i])
    return fixed_parts
步骤2:检查占位符

我们需要判断模板是否以占位符开头或结尾。

python

def has_leading_placeholder(template):
    return template.startswith('{')

def has_trailing_placeholder(template):
    return template.endswith('}')
步骤3:匹配标题

根据固定部分和占位符的情况,匹配标题字符串。具体逻辑如下:

  1. 如果模板的开头没有占位符,确保第一个固定部分匹配标题的开头。
  2. 如果模板的结尾没有占位符,确保最后一个固定部分匹配标题的结尾。
  3. 其他固定部分只需按顺序匹配即可。

python

def match_title(fixed_parts, title, leading_placeholder, trailing_placeholder):
    start = 0

    for index, part in enumerate(fixed_parts):
        if index == 0 and not leading_placeholder:
            # For the first fixed part, ensure it matches the start of the title
            pos = title.find(part, start)
            if pos != 0:
                return False
            start = pos + len(part)
        elif index == len(fixed_parts) - 1 and not trailing_placeholder:
            # For the last fixed part, ensure it matches the end of the title
            pos = title.rfind(part, start)
            if pos == -1 or pos + len(part) != len(title):
                return False
        else:
            pos = title.find(part, start)
            if pos == -1:
                return False
            start = pos + len(part)
    return True
主函数

主函数处理多个标题并输出结果。

python

def solution(n, template, titles):
    fixed_parts = parse_template(template)
    leading_placeholder = has_leading_placeholder(template)
    trailing_placeholder = has_trailing_placeholder(template)
    results = []
    for title in titles:
        if match_title(fixed_parts, title, leading_placeholder, trailing_placeholder):
            results.append("True")
        else:
            results.append("False")
    return ",".join(results)

感觉其实重点就是开头和结尾状态的判断~ 为了帮助广告平台判断标题是否符合创意模板,我们需要解决一个字符串匹配问题。这个问题的核心在于如何处理模板中包含的通配符,并判断给定的标题是否可以通过替换这些通配符生成。以下是详细的分析和解决方案。

问题分析

创意模板包含固定字符和通配符(用 {} 包围的部分),我们的任务是判断标题是否可以通过替换模板中的通配符生成。具体要求如下:

  1. 固定部分匹配:模板中不被 {} 包围的部分必须按顺序在标题中出现。

  2. 通配符替换:通配符可以替换为任意字符串,包括空字符串。

  3. 边界条件

    • 如果模板的开头或结尾没有通配符,标题的相应部分必须匹配模板的开头或结尾。
    • 如果模板的开头或结尾有通配符,标题只需包含模板的固定部分即可。

解决方案

我们可以将问题分解为以下步骤:

  1. 解析模板:将模板中的固定部分提取出来,忽略通配符。
  2. 检查边界条件:判断模板是否以通配符开头或结尾。
  3. 匹配标题:根据解析出的固定部分和边界条件,检查标题是否符合要求。
详细步骤
  1. 解析模板

    • 遍历模板字符串,提取出所有固定部分。
    • 遇到 { 时跳过,直到遇到 },然后继续提取固定部分。
  2. 检查通配符位置

    • 判断模板是否以 { 开头或以 } 结尾,以确定边界条件。
  3. 标题匹配逻辑

    • 从标题的开头开始匹配固定部分。
    • 如果模板不以通配符开头,首个固定部分必须从标题的开头匹配。
    • 如果模板不以通配符结尾,最后一个固定部分必须从标题的结尾匹配。
    • 其他固定部分只需按顺序出现在标题中即可。

完整代码

def parse_template(template):
    fixed_parts = []
    i = 0
    while i < len(template):
        if template[i] == '{':
            while i < len(template) and template[i] != '}':
                i += 1
            i += 1  # 跳过右“}”
        else:
            start = i
            while i < len(template) and template[i] != '{':
                i += 1
            fixed_parts.append(template[start:i])
    return fixed_parts

def has_leading_placeholder(template):
    return template.startswith('{')

def has_trailing_placeholder(template):
    return template.endswith('}')

def match_title(fixed_parts, title, leading_placeholder, trailing_placeholder):
    start = 0
	# 从哪一位开始,匹配后就前面的就不管了
    for index, part in enumerate(fixed_parts):
        if index == 0 and not leading_placeholder:
            # 保证开头没有自由替换的部分时匹配的字符串第一个部分也在开头
            pos = title.find(part, start)
            if pos != 0:
                return False
            start = pos + len(part)
        elif index == len(fixed_parts) - 1 and not trailing_placeholder:
            # 保证结尾没有自由替换的部分时匹配的字符串第一个部分也在结尾
            pos = title.rfind(part, start)
            # 找最后一个
            if pos == -1 or pos + len(part) != len(title):
                return False
        else:
            pos = title.find(part, start)
            if pos == -1:
                return False
            start = pos + len(part)
    return True

def solution(n, template, titles):
    fixed_parts = parse_template(template)
    leading_placeholder = has_leading_placeholder(template)
    trailing_placeholder = has_trailing_placeholder(template)
    results = []
    for title in titles:
        if match_title(fixed_parts, title, leading_placeholder, trailing_placeholder):
            results.append("True")
        else:
            results.append("False")
    return ",".join(results)

if __name__ == "__main__":
    #  You can add more test cases here
    testTitles1 = ["adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"]
    testTitles2 = ["CLSomGhcQNvFuzENTAMLCqxBdj", "CLSomNvFuXTASzENTAMLCqxBdj", "CLSomFuXTASzExBdj", "CLSoQNvFuMLCqxBdj", "SovFuXTASzENTAMLCq", "mGhcQNvFuXTASzENTAMLCqx"]
    testTitles3 = ["abcdefg", "abefg", "efg"]

    print(solution(4, "ad{xyz}cdc{y}f{x}e", testTitles1) == "True,False,False,True" )
    print(solution(6, "{xxx}h{cQ}N{vF}u{XTA}S{NTA}MLCq{yyy}", testTitles2) == "False,False,False,False,False,True" )
    print(solution(3, "a{bdc}efg", testTitles3) == "True,True,False" )