【每日一题0917】匹配头尾

:woman_mage:给定两个字符串s1和s2,s1可能是任意字母,例如s1 = abccd。s2可以是任意字母,例如s2 = xyyz。和s1不同之处是,s2中有可能包含一个星号*,它可以匹配任意字符(一个或多个)。请编写一个函数 compare(s1, s2) 来匹配s1和s2,如果匹配则返回True,否则返回False
示例:
输入:abccd, abccd,输出:True
输入:abccd, abcd,输出:False
输入:abccd, ab*d,输出:True
输入:abccd,ab*cy,输出:False

题目难度:简单
题目来源:董小春同学

def compare(s1: str, s2: str) -> bool:
    pass

assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("abccd", "ab*cy") is False
def match_begin_end(str1: str, str2: str) -> bool:
    index_num = str2.find("*")
    if index_num == -1:
        if str1 == str2:
            print("True")
            return True
        else:
            print("False")
            return False
    begin = str2[:index_num]
    end = str2[index_num + 1:]
    
    if begin == str1[:len(begin)] and end == str1[-len(end):]:
        print("True")
        return True
    else:
        print("False")
        return False

程序运行结果是对的,但是没有输入输出

def compare(s1: str, s2: str) -> bool:
    if s1 == s2:
        return  True
    if '*' in s2 and len(s1)>=len(s2):
        li = s2.split('*')
        if s1.startswith(li[0]) and s1.endswith(li[1]):
            return True
        else:
            return False
    else:
        return False


笨方法

def compare(s1:str,s2:str):
    len1=len(s1)
    len2=len(s2)
    if len1<len2:
        return False
    if '*' not in s2:
        if s1==s2:
            return True
        else:
            return False
    else:
        index=s2.find('*')
        if index==0:
            if s2[1:]==s1[(len1-len2+1):]:
                return True
            else:
                return False
        elif index==len2-1:
            if s2[:-1]==s1[:(-(1+len2-len1))]:
                return True
            else:
                return False
        else:
            if s2[0:index]==s1[0:index] and s2[index+1:]==s1[(len1-len2+1+index):]:
                return True
            else:
                return False
  public boolean compare(String s1, String s2) {
        if (s1.equals(s2)) {
            return true;
        }
        String[] split = s2.split("\\*");
        return s1.startsWith(split[0]) && s1.endsWith(split[1]);
    }

    @Test
    public void testCompare() {
        assert compare("abccd", "abccd");
        assert !compare("abccd", "abcd");
        assert compare("abccd", "ab*d");
        assert !compare("abccd", "ab*cy");
    }
import re

def compare(s1: str, s2: str) -> bool:
    return bool(re.match(s2.replace('*', '.*'), s1))

assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("abccd", "ab*cy") is False
2 个赞

首先想到的是根据字符串特点的写法。

def compare(s1: str, s2: str) -> bool:
    if '*' not in s2:
      return s1 == s2
    else:
      s3, s4 = s2.split('*')
      if (len(s3)+ len(s4) <= len(s1)-1 ) and s3 == s1[:len(s3)] and s4 == s1[-(len(s4)):]:
        return True
      else:
        return False

assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("abccd", "ab*cy") is Fals

看到 @lifq1984 使用了字符串操作方法,想到python中也应该有,于是替换这部分。

def compare(s1: str, s2: str) -> bool:
    if '*' not in s2:
      return s1 == s2
    else:
      s3, s4 = s2.split('*')
      if (len(s3)+ len(s4) <= len(s1)-1 ) and s1.startswith(s3) and s1.endswith(s4):
        return True
      else:
        return False

assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("abccd", "ab*cy") is False
assert compare("abccd", "abcc*bccd") is False  
assert compare("abccd", "ab*ccd") is False  # *不能匹配0个字符

最后看到 @hua123 学委使用正则的方法,确实这类匹配的题用正则应该是最不错的。
只是按照题意

s2中有可能包含一个星号* ,它可以匹配任意字符(一个或多个

s2替换时,应该是+,不是*

s2.replace('*', '.+')

也许还有哪里有错漏,还望各位赐教。 :laughing:

也许你没考虑这个情况。

assert compare("abccd", "abcc*bccd") is False
def compare(s1: str, s2: str) -> bool:
    l = len(s1) - len(s2)
    new_list1 = list(s1)
    new_list2 = list(s2)
    if l < 0:
        return False
    else:
        for i in range(len(new_list2)):
            if new_list2[i] == '*':
                new_list2.remove('*')
                for j in range(l+1):
                    new_list2.insert(i+j, new_list1[i])
        return new_list1 == new_list2



assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("abccd", "ab*cy") is False
def compare(s1: str, s2: str) -> bool:
    if '*' in s2:
        s2_list = s2.split("*")
        s2 = s2_list[0] + '*' * (len(s1) - len(s2) + 1) + s2_list[1]
    for i in range(len(s1)):
        if s1[i] != s2[i]:
            if s2[i] != '*':
                return False
    return True


assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("abccd", "ab*cy") is False
import re
def compare(s1: str, s2: str) -> bool:
    if s2.count("*") >0:
        s2= s2.replace("*","(.*)")
        if re.match(s2,s1) != None :
            return True
        else:
            return False
    else:
        return s1==s2

assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("abccd", "ab*cy") is False

好简洁,get 了 bool 函数

def compare(s1: str, s2: str) -> bool:
    if s1 == s2:
        return True
    elif "*" in s2:
        l = s2.split("*")
        if s1.startswith(l[0]) and s1.endswith(l[1]):
            return True
        else:
            return False
    else:
        return False


assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("abccd", "ab*cy") is False
assert compare("abc", "ab*c") is False

由于*表示1个或多个,而不是0个或多个;这种情况下应该是False才对;
但我看回答中基本都没考虑到
如果用的正则的话,则下面的情况也没考虑到:

assert compare("abccd", "*c") is False

比较完整的测试用例

assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("ccdab", "ab*d") is False
assert compare("abccd", "ab*cy") is False
assert compare("abccd", "*") is True
assert compare("abccd", "a*") is True
assert compare("abccd", "c*") is False
assert compare("abccd", "*d") is True
assert compare("abccd", "*c") is False
assert compare("abc", "ab*c") is False

我没看清题,理解成可以有多个*了

def compare2(s1: str, s2: str) -> bool:
    s2_list = s2.split('*')
    last_index = 0
    for i in range(len(s2_list)):
        if last_index >= len(s1): return False
        if i == 0 :
            if not s1.startswith(s2_list[i]): return False
        elif i == len(s2_list)-1:
            if not s1.endswith(s2_list[i]): return False
        else:
            new_index = s1.find(s2_list[i],last_index)
            if new_index < last_index: return False
        last_index += len(s2_list[i])+1
    return True

assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("ccdab", "ab*d") is False
assert compare("abccd", "ab*cy") is False
assert compare("abccd", "*") is True
assert compare("abccd", "a*") is True
assert compare("abccd", "c*") is False
assert compare("abccd", "*d") is True
assert compare("abccd", "*c") is False
assert compare("abc", "ab*c") is False

assert compare("abccd", "**") is True
assert compare("abccdjalsdjf", "*c*") is True
assert compare("abccdjalsdjf", "a*c*") is True
assert compare("abccdjalsdjf", "a*c*f") is True
assert compare("abccdjalsdjf", "*c*f") is True
assert compare("abccdjalsdjf", "a*d*z*f") is False
assert compare("abccdjalsdjf", "c*y*d") is False
import re
def compare(s1: str, s2: str) -> bool:
    match_obj = re.match(s2.replace('*','.+'),s1)
    return s1 == match_obj.group() if bool(match_obj) else False

感谢楼上的测试用例

def compare(s1: str, s2: str) -> bool:
    indexstar = s2.find('*')
    if indexstar == -1:
        if s1 == s2:
            return True
        else:
            return False
    head = s2[:indexstar]
    tail = s2[indexstar + 1:]
    if head == s1[:len(head)] or len(head) == 0:
        if tail == s1[-len(tail):] or len(tail) == 0:
            if len(s1) >= len(s2):
                return True
    return False
def compare(s1: str, s2: str) -> bool:
    if '*' not in s2:
        if s1 == s2:
            return True
        else:
            return False
    else:
        s2_lsit = s2.split('*')
        if s1[0:len(s2_lsit[0])] == s2_lsit[0] and s1[-len(s2_lsit[-1]):] == s2_lsit[-1]:
            return True
        else:
            return False
assert compare("abccd", "abccd") is True
assert compare("abccd", "abcd") is False
assert compare("abccd", "ab*d") is True
assert compare("abccd", "ab*cy") is False

这里如果*号在第一个位置或者最后一个位置,是不是会有问题?