前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Q792 Number of Matching Subsequences

Q792 Number of Matching Subsequences

作者头像
echobingo
发布2018-10-10 11:41:53
3740
发布2018-10-10 11:41:53
举报
文章被收录于专栏:Bingo的深度学习杂货店

Given string S and a dictionary of words words, find the number of words[i] that is a subsequence of S.

Example :
代码语言:javascript
复制
Input: 
S = "abcde"
words = ["a", "bb", "acd", "ace"]
Output: 3

Explanation: There are three words in words that are a subsequence of S: 
"a", "acd", "ace".
Note:
代码语言:javascript
复制
All words in words and S will only consists of lowercase letters.
The length of S will be in the range of [1, 50000].
The length of words will be in the range of [1, 5000].
The length of words[i] will be in the range of [1, 50].
解题思路:

思路1:将 S 与 words 中的 word 一个个匹配,计数。时间复杂度很高,超时。见Python实现部分。

思路2:把 S 中各个字符的下标位置用字典列表保存起来(之所以用字典列表,是因为 S 中可能有重复的字母)。见Python实现2部分。

例如,S = "aabcbbac",那么得到的字典列表为: { "a" : [0,1,6], "b" : [2,4,5], "c" : [3,7] }

然后对于 words 中的每一个 word,计算 word 中每个字符与字典列表中每个字符的位置关系。这里有很多个小注意点:

举例1:word = "acac", i = 0 时,取 "a" ,0 >= i,因此 "a" 匹配;i =1 时,取 "c",3 >= i,因此 "c" 匹配;但是当 i = 2 时,取 "a",发现字典列表中 "a" 的前两个位置 0、1 都不行,但是第三个位置 6 可以,它满足 6 >= i ,所以也是匹配。因此在判断某个字符匹配时,这里应该是一个for循环,目的是找到能匹配的正确的位置。同理,c 的位置 7 寻找也是一样。

举例2: word = "acca",前 3 个字符都能匹配,这个不用多说。但是当 i = 3 时,取 "a",我们如果采取例子 1 中的方法,会发现 6 >= i,是匹配的。但是我们观察字符串,发现 "acca" 并不是 S 的子序列。因此,举例 1中还缺少限制条件。通过分析可以发现,因为在找上一个字符 "c" 时,S 的位置已经到达了 7 的位置,所以我们在找字典列表时,找的位置要大于 7,因为 6 < 7,所以不可以。因此,我们用一个变量保存上一次找到的 S 的位置,在 if 判断中加入一个限制,即当前在字典列表中寻找的字符下标要大于上一次寻找到的字符下标。 如果遍历完字典列表中的 "a" 的所有位置还是不满足,那么说明不是子序列,返回 0。

Python实现:
代码语言:javascript
复制
# 超时
class Solution:
    def numMatchingSubseq(self, S, words):
        """
        :type S: str
        :type words: List[str]
        :rtype: int
        """
        count = 0
        for word in words:
            count += self.findSubSeq(word, S)
        return count

    def findSubSeq(self, word, S): 
        i = j = 0
        slen, wlen = len(S), len(word)
        while i < slen:
            # 两字符串索引都不能越界 + S 剩余长度要比 word 剩余长度长(减少运行时间) + 当前字符能匹配
            while i < slen and j < wlen and slen - i >= wlen - j and S[i] == word[j]:
                j += 1
                i += 1
            i += 1
        return 1 if j == wlen else 0
Python实现2:
代码语言:javascript
复制
# 不超时
from collections import defaultdict
class Solution2:
    def numMatchingSubseq(self, S, words):
        """
        :type S: str
        :type words: List[str]
        :rtype: int
        """
        def findSubSeq(word): 
            last_i = -1
            for i, v in enumerate(word):
                if not dic_s[v]:  # 如果word中出现S中不存在的字符
                    return 0
                for cur_i in dic_s[v]:
                    if last_i < cur_i and cur_i >= i:  
                        last_i = cur_i 
                        break
                    if cur_i == dic_s[v][-1]:
                        return 0
            return 1

        dic_s = defaultdict(list)
        # 字典列表记录每个字母出现的位置
        for i, v in enumerate(S):
            dic_s[v].append(i)
        count = 0
        for word in words:
            count += findSubSeq(word)
        return count

S = "aabcbbac"
words = ["acac", "acca", "acc"]
print(Solution().numMatchingSubseq(S, words))  # 2
print(Solution2().numMatchingSubseq(S, words))  # 2
补充知识:

1、字典列表的初始化方法: 可以采用 collections 中的 defaultdict(list) 进行初始化。

代码语言:javascript
复制
from collections import defaultdict
dic_s = defaultdict(list)
        # 字典列表记录每个字母出现的位置
        for i, v in enumerate(S):
            dic_s[v].append(i)

2、复制字典的浅拷贝与深拷贝:

  • 如果 A 是一个字典,B = A 是传引用,A、B 会同时改变。
  • 如果 A 是一个字典,B = A.copy() 对于一层来说(比如字典中存储的是字符串)是深拷贝,对于超过一层来说(比如字典中存储的是列表)是浅拷贝。深拷贝修改 A、B 的值相互不影响,但是浅拷贝是相互影响的,即外层不会同时改变,内层(如列表中的元素)会同时改变。所以如果想要复制字符串字典采用 copy() 可行,但复制字典列表不可行。
  • 复制字典不受层数约束的深拷贝方法需要用到 copy 模块中的 deepcopy() 函数。此时,无论字典有几层,A、B都是相互独立的,不会因其中一方的改变而改变。用法如下:
代码语言:javascript
复制
from copy import deepcopy
B = deepcopy(A)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.09.26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Example :
  • Note:
  • 解题思路:
  • Python实现:
  • Python实现2:
  • 补充知识:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档