青训营-创意标题匹配问题

269 阅读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

解题思路

为了解决这个问题,我们可以利用正则表达式的强大匹配能力将模板转换为正则表达式

  • {}部分转换为.*,用于匹配任意字符
  • 非通配符字段需要与标题中的字符完全一致,因此我们需要对这些字符进行处理,使其在正则表达式中正确表示出来(需要转义)

逐个标题进行匹配

  • 通过构建正则表达式来描述模板的结构,我们可以利用std::regex_match来判断给定的标题是否符合模板
  • 输出结果

具体步骤

1.模板先转换为正则表达式字符串regexPattern

  • 遍历模板中的每个字符
  • 遇到{},正则表达式字符串regexPattern就+.*
  • 遇到非通配符就要进行转义

2.转义 如果字符是正则表达式里的特殊函数,要+\\进行转义 否则直接添加原始字符
填充构造函数 string(size_t n, char c)
该函数将填充 char c 的 n 个拷贝到string中。

    char c = 'A'; 
    std::string s(1, c);

3.遍历标题,判断是否匹配 利用regex_match(要匹配的字串,正则表达式对象)进行匹配
注意这里要将正则表达式字符串转为正则表达式对象

regex_match

完全匹配,即要求整个字符串符合匹配规则,返回true或false
完全匹配,必须从头到尾符合模式"^" + regexPattern + "$"

4.result字符串记录结果并输出

算法实现

#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include<regex>


// 判断每个标题是否符合模板,并返回结果字符串
std::string solution(int n, const std::string& titleTemplate, const std::vector<std::string>& titles) {
   std::string regexPattern;//正则表达式字符串
   bool insidebraces =false;//通配符区间
   for(char c:titleTemplate){//遍历模板
    if(c=='{'){
     insidebraces=true;
     regexPattern=regexPattern+".*";
    }else if(c=='}'){
        insidebraces=false;
    }else if(insidebraces==false){
        regexPattern=regexPattern+std::string(1,c);//进行转义,由于本题仅有字母,因此无需考虑特殊字符
    }
   }
   regexPattern='^'+regexPattern+'$';
   std::string result;
    for(std::string a:titles){
             if(std::regex_match(a,std::regex(regexPattern)))//进行匹配
             {
                result=result+"True,";
             }else result=result+"False,";
    }
  result=result.substr(0,result.length()-1);//删除','

  return result;



}

int main() {
    std::vector<std::string> testTitles1 = {"adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"};
    std::vector<std::string> testTitles2 = {"CLSomGhcQNvFuzENTAMLCqxBdj", "CLSomNvFuXTASzENTAMLCqxBdj", 
                                             "CLSomFuXTASzExBdj", "CLSoQNvFuMLCqxBdj", 
                                             "SovFuXTASzENTAMLCq", "mGhcQNvFuXTASzENTAMLCqx"};
    std::vector<std::string> testTitles3 = {"abcdefg", "abefg", "efg"};

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

    return 0;
}