问题描述
创意标题匹配问题
在广告平台中,为了给广告主一定的自由性和效率,允许广告主在创造标题的时候以通配符的方式进行创意提交。 线上服务的时候,会根据用户的搜索词触发的 bidword 对创意中的通配符(通配符是用成对 {} 括起来的字符串,可以包含 0 个或者多个字符)进行替换,用来提升广告投放体验。 例如:“{末日血战} 上线送 SSR 英雄,三天集齐无敌阵容!”,会被替换成“帝国时代游戏下载上线送 SSR 英雄,三天集齐无敌阵容!”。给定一个含有通配符的创意和n个标题,判断这句标题是否从该创意替换生成的。
解题思路
这个题目有点类似于正则表达式的实现,不过要比实现正则表达式更为简单,因为我们只需要考虑{}中的替换。实际上就是判断除{} 内的内容外,其余部分是否相等的问题。我们首先来考虑只有一个{}时的情况。在只有一个{}的时候,也可以从三种情况来考虑:第一种是{}出现在最开始,即类似于{abc}xyz这样的情况,第二种是{}出现在最后,即类似于xyz{def}这样的情况。第三种也就是相对比较麻烦的情况是{}出现在中间位置,即类似于ad{xyz}cdc这样的情况。
为了处理过程更加统一,我们可以把前两种情况看成是第三种情况的特殊情况,也就是前面或者后面为空的情况。这样的话我们就可以按照{}出现在中间位置进行统一考虑。当只有一对{}时,具体步骤就是先判断创意字符串和标题字符串在{的前面部分是否相等,将相同位置上的字符比较即可,然后再判断}后面的部分是否相等。如果两个都相等,则是由创意替换生成的,否则就不是。
比如,有个创意是ad{xyz}cdc,标题是adfcdc,我们先找到{的位置下标是2,}的位置下标是6,那么就比较2之前的部分两者是否相等,在比较分别从最后一个位置开始比较,到创意坐标为7的位置是否相等。按照这样的方式推理到多个{}时的处理方法就是,同样需要先判断开始和最后部分是否相等,然后找到两个花括号中的内容,判断标题字符串是否包含有该部分的内容,然后找到下一个两个花括号中的内容。可以不需要指出创意标题中的该部分字符串具体在标题字符串中的哪个位置,有就可以,但是要保证顺序是一致的。
解题代码
public class Main {
public static String solution(int n, String template, String[] titles) {
// Please write your code here
StringBuffer results = new StringBuffer();
String[] splite = new String[]{};
int num = 0;
for(int i=0;i<titles.length;i++){
int first = 0;
int last = template.length() - 1;
int index1 = 0; // 前一个‘}’
int index2 = 0; // 后一个‘{’
//开始是否匹配
if(template.charAt(0) != '{'){
while(template.charAt(first) != '{'){
first++;
}
if(!template.substring(0,first).equals(titles[i].substring(0,first))){
results.append("False");
num++;
if(i != titles.length - 1){
results.append(',');
}
continue;
}
}
//结尾是否匹配
if(template.charAt(last) != '}'){
int gap = 0;
while(template.charAt(last) != '}'){
last--;
}
gap = template.length()-1 - last;
if(!template.substring(last+1,template.length()).equals(titles[i].substring(titles[i].length()-gap,titles[i].length()))){
results.append("False");
num++;
if(i != titles.length - 1){
results.append(',');
}
continue;
}
}
//找到第一个‘}’
index1 = first;
while(template.charAt(index1) != '}'){
index1++;
}
//找到最后一个'{'
while(template.charAt(last) != '{'){
last--;
}
//就只有一个{}
if(first == last){
results.append("True");
num++;
if(i != titles.length - 1){
results.append(',');
}
continue;
}
// if(index1 == template.length() - 1){
// results.append("True");
// num++;
// if(i!= titles.length - 1){
// results.append(',');
// }
// continue;
// }
//检查中间的
//即每次检查{}~{}两个花括号之间的是否相等
int k = 0;
while(index2 < last){
int j = index1++;
while(template.charAt(j) != '{'){
j++;
}
index2 = j;
String tmp = template.substring(index1,j);
String title = titles[i].substring(k);
//这里k > titles[i].indexOf(tmp)的意思是虽然标题字符串中有创意字符串{} {}之中的字符,但是他们的相对位置不对
//就是说在找到第一次出现了的前一部分字符串位置之后,后面字符串中的对应部分应该包含对应字符串
//例如应该是{}abc{}df{},但是变成了{}df{}abc{}
if(!titles[i].contains(tmp)|| k > title.indexOf(tmp)){
results.append("False");
num++;
break;
}
k = title.indexOf(tmp);
index1 = j;
while(template.charAt(index1) != '}'){
index1++;
}
}
//System.out.println(num);
if(index2 == last && num < i+1){
results.append("True");
num++;
}
if(i != titles.length - 1){
results.append(',');
}
}
return results.toString();
}
public static void main(String[] args) {
// You can add more test cases here
String[] testTitles1 = {"adcdcefdfeffe", "adcdcefdfeff", "dcdcefdfeffe", "adcdcfe"};
String[] testTitles2 = {"CLSomGhcQNvFuzENTAMLCqxBdj", "CLSomNvFuXTASzENTAMLCqxBdj", "CLSomFuXTASzExBdj", "CLSoQNvFuMLCqxBdj", "SovFuXTASzENTAMLCq", "mGhcQNvFuXTASzENTAMLCqx"};
String[] testTitles3 = {"abcdefg", "abefg", "efg"};
String[] test = {"xyzdef","abcdef","abxyzdef","xyz","abxyz"};
//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"));
System.out.println(solution(5, "{abc}xyz{def}", test));
}
}
总结
这个题目对我来说最特别的点就是该如何判断中间部分的标题字符串是否由创意字符串变化而来的问题。虽然很容易就知道是要判断除了{}之外的部分是否相等,但是我们无法确定到底是从哪里开始,再到哪里结束才是标题字符串中对应的创意字符串的部分,因为很有可能替换的{}中的内容和创意字符串的其它部分相等。因此就要转化为标题字符串中是否包含该部分字符串,如果包含,找到第一次出现的位置,那么后面相匹配的字符部分要么就包含有创意字符串的后面除{}内的部分,找不到就说明标题字符串中不存在或者顺序不一致。
由于这个题目的测试用例比较少,题目也是早期做的,所以如果解法还存在不妥当的地方,希望能批评指出,谢谢。