二、字符串(37)524. 通过删除字母匹配到字典里最长单词

524. 通过删除字母匹配到字典里最长单词

 

给你一个字符串 s 和一个字符串数组 dictionary ,找出并返回 dictionary 中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。

如果答案不止一个,返回长度最长且字母序最小的字符串。如果答案不存在,则返回空字符串。

示例 1:

输入:s = "abpcplea", dictionary = ["ale","apple","monkey","plea"]
输出:"apple"
示例 2:

输入:s = "abpcplea", dictionary = ["a","b","c"]
输出:"a"
 

提示:

1 <= s.length <= 1000
1 <= dictionary.length <= 1000
1 <= dictionary[i].length <= 1000
s 和 dictionary[i] 仅由小写英文字母组成

 

贪婪匹配:匹配最长的字符串

正则表达式通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。比如这个表达式:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab,这被称为贪婪匹配。

'''
字符串的比较操作:
    运算符:>,>=,<,<=,==,!=   比较的是字母顺序
	比较规则:首先比较两个字符串中的第1个字符,如果相等则继续比较下一个字符,依次比较下去,直到两个字符串中的字符不相等时,其比较结果就是两个字符串的比较结果,两个字符串中的所有后续字符将不再被比较
    比较原理:两字符进行比较时,比较的是其ordinal value(原始值),调用内置函数ord可以得到指定字符的ordinal value(ASCII码)。与内置函数ord对应的是内置函数chr,调用内置函数chr时指定ordinal value可以得到其对应的字符
	== 与 is 的区别:
    	== 比较的是value
    	is 比较的是id
'''
class Solution:
    def findLongestWord(self, s: str, dictionary: List[str]) -> str:
        res = ""#返回的字符串
        for t in dictionary:#遍历字典中的每一个字符串
            i = j = 0#双指针
            #注意:从题意可以看出t和s的元素的顺序是一样的s: aabbcc t: abc
            while i < len(t) and j < len(s):#i执行字符数组中的元素,j指向字符串s,直到遍历完其中一方后结束,s是主串,t是子串
                if t[i] == s[j]:#两个指针指向的元素相等
                    i += 1
                j += 1
            if i == len(t):#i到数组中的字符串的尾部越界,遍历完了这个字符串,说明这个字符串是子串
                if len(t) > len(res) or (len(t) == len(res) and t < res):#长度长或者长度一样但是字母序小时
                    res = t
        return res

 

方法二:排序
思路和算法

在方法一的基础上,我们尝试通过对 dictionary 的预处理,来优化第 2 个问题的处理。

我们可以先将 dictionary 依据字符串长度的降序和字典序的升序进行排序,然后从前向后找到第一个符合条件的字符串直接返回即可。

class Solution:
    def findLongestWord(self, s: str, dictionary: List[str]) -> str:
        '''
        将dictionary这个字典,先按照长度从大到小排序,如果长度相同的情况下,按照字母大小排序(ASCII编码顺序)
        1. sorted()函数
        sorted()函数是Python的内置函数,此函数不改变原序列,在排序后会生成一个新的序列。调用时,一般只需要给出一个序列即可,该序列可以是列表,字典,元组,字符串。其余参数取默认值,默认为升序排序。最终结果将返回一个以列表为容器的返回值。若该序列为字典,将返回键的列表
        2.sort()方法
sort()方法是Python中列表的内建函数,此方法改变原序列,即原地排序,不生成新的序列,且无返回值,默认为升序排序。字典、元组、字符串不具有sort()方法。

括号中:key = lambda x:(-len(x),x)  表明sort()的排序准则。

排序准则比如说是从按字母从小到大排序,或者是按字符串长度排序。

排序的准则在x:()中,这里的(-len(x),x) 表明有两个排序原则。

首先,按照-len(x)排序,len(x)表明将长度从小到大排序,那么-len(x)表明将字符串从大到小排序;
如果出现两个字符串长度相同的情况,按照第二个x,也就是按照x的大小,从小到大排序。比如说:abs和abc两个字符串,按照key = lambda x:(-len(x),x) ) 的排序准则的话,abc会在abs前面。

测试案例(python):

dictionary = ['abc','abcd','abs','bc']
sorted(dictionary, key=lambda x: (-len(x), x))
print(dictionary)

# 输出为:['abcd','abc','abs','bc']
sort 和 sorted区别
sorted()函数:列表写在里面sorted(l,key=lambda x:x);
sort()函数:列表写在外面l.sort(key = lambda x:x);

sorted()函数:返回一个排序后的新序列,不改变原始序列;
sort()函数:没有返回值,直接改变原始序列;


'''
        dictionary.sort(key=lambda x: (-len(x), x))#这个dictionary是一个列表相当于a.sort() a是列表,对a这个列表进行排序
        for t in dictionary:
            i = j = 0
            while i < len(t) and j < len(s):
                if t[i] == s[j]:
                    i += 1
                j += 1
            if i == len(t):
                return t
        return ""

 

方法三: 

class Solution:
    def findLongestWord(self, s: str, dictionary: List[str]) -> str:

        #构建二维数组
        m = len(s)#主串的长度
        #[0] * 26 【0, 0,。。。,0】
        #range(m) 0 - m-1
        f = [[0] * 26 for _ in range(m)] #构造一个m行26列的二维数组
        f.append([m] * 26)#在最后面添加一行元素,改行元素都是m

        #填充二维数组
        for i in range(m - 1, -1, -1):#从后到前,m-1 到 0 
            for j in range(26):#0-25从左遍历到右
                if ord(s[i]) == j + 97:#j + 97表示j这个位置对应的字母的数值  ord(s[i])表示s这个主字符串中的当前元素
                    f[i][j] = i#相等时在相应位置赋值
                else:
                    f[i][j] = f[i + 1][j]#不等时,使用后面一行的值,因为f[i][j]=f[i+1][j]
        
        #进行主串和子串的匹配
        res = ""#初始空字符串
        for t in dictionary:
            match = True#默认匹配成功
            j = 0#指向主串s
            for i in range(len(t)):# i从0到len(t)-1,遍历t
                if f[j][ord(t[i]) - 97] == m:#ord(t[i]) - 97用于表示t中该元素对应的在s中第一次出现的位置,如果是m,则表示该元素不存在s中
                    match = False
                    break
                j = f[j][ord(t[i]) - 97] + 1#存在则更新j的值,因为现在f[j][ord(t[i]) - 97]这个位置本次匹配成功了,下次从下一个位置开始
            if match:#匹配成功,res放长的或者是一样长但是小的
                if len(t) > len(res) or (len(t) == len(res) and t < res):
                    res = t
        return res

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值