【c++子串匹配】创意标题匹配问题 | 豆包MarsCode KK 刷题 No.7

111 阅读3分钟

哈喽every body!!
搞了几个小时,终于把这个问题ac了。
看了网上的题解都是python正则。这里提供了一个另一个方法。

题目介绍

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

测试样例

样例1:

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

样例2:

输入:n = 3, template = "a{bdc}efg", titles = ["abcdefg", "abefg", "efg"]
输出:"True,True,False"

思路分析

  1. {}可以看做成一个分隔符。将原始的字符串template分隔成若干个子串
  2. 任务转化:判断子串问题。将这若干个子串,挨个去和titles中的标题字符串进行比较,即判断子串是否在标题字符串中
  3. 边界条件:
    • 后一个子串在titles字符串中的初始位置一定大于前一个子串的末尾。
    • 如果最后一个子串的最后一个字符与titles字符串的末尾不一致,且titles字符串的末尾不为},则直接判定为false

功能设计

  1. 提取子串的函数 extractFixedParts()
  2. 检验子串是否满足边界条件 checkSubstrings()
vector<string> extractFixedParts(const string& template_) {
    vector<string> fixedParts;
    size_t i = 0;
    while (i < template_.size()) {
        if (template_[i] == '{') {
            // 跳过通配符部分
            while (i < template_.size() && template_[i] != '}') {
                ++i;
            }
            ++i; // 跳过右“}”
        } else {
            // 记录固定部分的起始位置
            size_t start = i;
            while (i < template_.size() && template_[i] != '{') {
                ++i;
            }
            // 提取固定部分并添加到结果向量中
            fixedParts.push_back(template_.substr(start, i - start));
        }
    }
    return fixedParts;
}
bool checkSubstrings(const std::vector<std::string>& substrings, const std::string& S) {
    size_t last_end = 0; // 记录上一个子串的末尾位置

    for (const auto& a : substrings) {
        size_t pos = S.find(a, last_end);
        if (pos == std::string::npos) {
            return false; // 当前子串不是 S 的子串
        }
        last_end = pos + a.size(); // 更新上一个子串的末尾位置

        if(substrings.back().back()!='}'){
            if(substrings.back().back()!=S.back()){
                return false;
            }
        }
    return true; // 所有子串都满足条件
}

完整代码

#include <iostream>
#include <string>
#include <vector>
#include <numeric>
using namespace std;

bool checkSubstrings(const std::vector<std::string>& substrings, const std::string& S,const string& template_ ) {
    size_t last_end = 0; // 记录上一个子串的末尾位置
     for (const auto& a : substrings) {
    cout<<a<<" ";}
    cout<<endl;
    for (const auto& a : substrings) {
        size_t pos = S.find(a, last_end);
        if (pos == std::string::npos) {
            cout<<a<<" NOT SUB-"<<endl;;
            return false; // 当前子串不是 S 的子串
        }
        last_end = pos + a.size(); // 更新上一个子串的末尾位置
        }

        if(template_.back()!='}'){
            if(substrings.back().back()!=S.back()){
                cout<<substrings.back()<<"NOT SUB"<<endl;;
                return false;
            }
        
        }
    return true; // 所有子串都满足条件

}

vector<string> extractFixedParts(const string& template_) {
    vector<string> fixedParts;
    size_t i = 0;
    while (i < template_.size()) {
        if (template_[i] == '{') {
            // 跳过通配符部分
            while (i < template_.size() && template_[i] != '}') {
                ++i;
            }
            ++i; // 跳过右“}”
        } else {
            // 记录固定部分的起始位置
            size_t start = i;
            while (i < template_.size() && template_[i] != '{') {
                ++i;
            }
            // 提取固定部分并添加到结果向量中
            fixedParts.push_back(template_.substr(start, i - start));
        }
    }
    return fixedParts;
}

string solution(int n, std::string template_,
                     std::vector<std::string> titles) {

    vector<pair<int, int>> wildcards;
    int i = 0;
    while (i < template_.size()) {
        if (template_[i] == '{') {
            int start = i;
            while (i < template_.size() && template_[i] != '}') i++;
            wildcards.push_back({start, i});
        }
        i++;
    }

    vector<string> s = extractFixedParts(template_);
    vector<string> result(n, "False");
    for(int i=0;i<n;i++){
        if(checkSubstrings(s,titles[i],template_)){
            result[i] = "True";
            cout<<titles[i]<<" IS TRUE"<<endl;
        }

    }

    // 用于存储结果的字符串             
  // Please write your code here
  // ans format:"True,False,False,True"
  cout<<std::accumulate(result.begin(), result.end(), std::string(),
                         [](const std::string& a, const std::string& b) {
                           return a.empty() ? b : a + "," + b;
                         })<<endl;
  return std::accumulate(result.begin(), result.end(), std::string(),
                         [](const std::string& a, const std::string& b) {
                           return a.empty() ? b : a + "," + b;
                         });

}

int main() {
  //  You can add more test cases here
  
  std::vector<std::string> testTitles2 = {
      "CLSomGhcQNvFuzENTAMLCqxBdj", "CLSomNvFuXTASzENTAMLCqxBdj",
      "CLSomFuXTASzExBdj",          "CLSoQNvFuMLCqxBdj",
      "SovFuXTASzENTAMLCq",         "mGhcQNvFuXTASzENTAMLCqx"};
  //std::vector<std::string> testTitles3 = {"abcdefg", "abefg", "efg"};

  
  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;
}

}