问题描述
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候,会根据用户的搜索词触发的 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"
样例3:
输入:
n = 5, template = "{abc}xyz{def}", titles = ["xyzdef", "abcdef", "abxyzdef", "xyz", "abxyz"]
输出:"True,False,True,True,True"
老样子我们先进行问题分析
我们有一个含有通配符(用成对 {} 括起来的字符串,可以包含 0 个或多个字符)的创意字符串,以及 n 个标题字符串。
需要判断每个给定的标题是否是由该创意字符串通过将通配符替换为特定内容而生成的。
具体解决方案思路:
1. 处理通配符
首先需要从创意字符串中识别出通配符部分。可以通过遍历创意字符串,当遇到 { 时,记录下当前位置,然后继续遍历直到遇到 },这样就确定了一个通配符的起止位置,从而提取出通配符内容。
将提取出的通配符内容存储起来,以便后续在匹配标题时进行对比和替换操作的验证。
2. 标题匹配验证
对于每个给定的标题,同样进行遍历操作。
当遍历到创意字符串中的非通配符部分时,与标题中的相应位置字符进行严格匹配,若不匹配则该标题不是由该创意替换生成的。
当遇到创意字符串中的通配符部分时,在标题中对应位置查找是否存在与之前提取的通配符内容相匹配的子字符串。如果存在,则继续往后验证;如果不存在,则该标题不是由该创意替换生成的。
结构体定义:
typedef struct WCInfo {
char *cont;
int st;
int en;
struct WCInfo *next;
WCInfo *extractWC(const char *creatStr) {
WCInfo *head = NULL;
WCInfo *tail = NULL;
int creatLen = strlen(creatStr);
int i = 0;
while (i < creatLen) {
if (creatStr[i] == '{') {
int st = i;
i++;
while (i < creatLen && creatStr[i]!= '}') {
i++;
}
int en = i;
// 分配内存存储通配符内容
char *wcCont = (char *)malloc((en - st) * sizeof(char));
strncpy(wcCont, creatStr + st + 1, en - st - 1);
wcCont[en - st - 1] = '\0';
// 创建新的通配符信息节点
WCInfo *newNode = (WCInfo *)malloc(sizeof(WCInfo));
newNode->cont = wcCont;
newNode->st = st;
newNode->en = en;
newNode->next = NULL;
if (head == NULL) {
head = newNode;
tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
i++;
} else {
i++;
}
}
return head;
}
---关键(KEY)
具体 算法 步骤:
1. 提取创意字符串中的通配符信息
创建一个列表(或数组,根据具体编程语言而定),用于存储通配符及其在创意字符串中的位置信息。
初始化一个指针 i 用于遍历创意字符串,从 i = 0 开始。
进入循环,只要 i 小于创意字符串的长度:
如果创意字符串的第 i 个字符是 {,则记录下当前位置 start = i,然后继续遍历直到遇到 },记录下结束位置 end = i,并提取出通配符内容 wildcard_content = creative_string[start + 1:end](这里是根据具体编程语言的字符串切片操作来提取子字符串),将 (wildcard_content, start, end) 作为一个元组(或结构体,根据语言特性)添加到存储通配符信息的列表中。
然后将 i 更新为 end + 1,继续下一轮遍历。
2. 判断标题是否由创意替换生成
对于每个给定的标题:
1.初始化一个指针 j 用于遍历标题字符串,从 j = 0 开始,同时初始化一个指针 k 用于遍历创意字符串,从 k = 0 开始。
2.进入循环,只要 k 小于创意字符串的长度且 j 小于标题字符串的长度:
3.如果创意字符串的第 k 个字符不是 {(即非通配符部分),则比较创意字符串的第 k 个字符与标题字符串的第 j 个字符,若不相等则该标题不是由该创意替换生成的,直接返回 False;若相等,则将 j 和 k 都往后移动一位,继续下一轮比较。
4.如果创意字符串的第 k 个字符是 {,则根据之前存储的通配符信息,找到当前通配符对应的内容 wildcard_content 及其在创意字符串中的起止位置 start 和 end。然后在标题字符串中从 j 位置开始查找是否存在与 wildcard_content 匹配的子字符串,若不存在则该标题不是由该创意替换生成的,直接返回 False;若存在,找到匹配的子字符串后,将 j 更新为匹配子字符串在标题字符串中的结束位置的下一位,将 k 更新为 end + 1,继续下一轮比较。
5.如果循环结束后,k 等于创意字符串的长度且 j 等于标题字符串的长度,说明该标题是由该创意替换生成的,返回 True;否则,返回 False。
附具体C语言代码(参考)
int isTitleGen(const char *creatStr, const char *title, WCInfo *wcInfo) {
int creatLen = strlen(creatStr);
int titleLen = strlen(title);
int j = 0;
int k = 0;
while (k < creatLen && j < titleLen) {
if (creatStr[k]!= '{') {
if (creatStr[k]!= title[j]) {
return 0;
}
j++;
k++;
} else {
WCInfo *curr = wcInfo;
while (curr!= NULL) {
if (strstr(title + j, curr->cont)!= NULL) {
int matchEnd = (int)(strstr(title + j, curr->cont) - title) + strlen(curr->cont);
j = matchEnd;
k = curr->en + 1;
break;
}
curr = curr->next;
}
if (curr == NULL) {
return 0;
}
}
}
return k == creatLen && j == titleLen;
}
小小的简单题曾给我带来大大的震撼😂,我们也通过这道例题了解到通配符替换在创意展示中的应用,体现编程解决实际问题价值。
简短总结一下所考察的知识点:有字符串处理,涵盖遍历、匹配、子串提取查找,及链表构建维护(存储通配符信息),检验基础与综合运用能力,像这样的“简单题”也同样有助于夯实编程基本功、提升逻辑思维。