给定字符串 S 和单词字典 words, 求 words[i] 中是 S 的子序列的单词个数。
示例:
输入:
S = "abcde"
words = ["a", "bb", "acd", "ace"]
输出: 3
解释: 有三个是 S 的子序列的单词: "a", "acd", "ace"。
注意:
所有在words和 S 里的单词都只由小写字母组成。
S 的长度在 [1, 50000]。
words 的长度在 [1, 5000]。
words[i]的长度在[1, 50]。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-matching-subsequences
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一种思路:
麻瓜解,
对于words里每个单词,都用LeetCode-Python-392. 判断子序列(字符串 + 双指针)的方法处理一遍,
时间复杂度:O(len(S) * len(words))
空间复杂度:O(1)
比较麻瓜也比较简单,所以没有实现。
第二种思路:
每个word都要扫一遍 S 真的是太麻瓜了,这个时候考虑,空间换时间,
所以可以开一个哈希表,key是每个小写字母,val是一个list,里面【升序】存放所有这个小写字母在S里出现的下标。
这样对于每个word,只要能让其每个元素在S里出现的下标呈递增的趋势,则这个word就是S的子序列。
从贪心的角度出发,应该让word里每个元素取比它【前一个元素下标(pre)大的】最小的那个下标,
这个下标怎么找?
数组有序,暗示二分。
二分完如果存在合理的下标,就刷新pre, 然后继续处理剩下的元素,如果没有找到这样的下标,则说明这个word不行。
时间复杂度: O(len(S)+ len(words) * len(最长的word) * (log(S里最多的字母出现的频率)))
空间复杂度:O(len(S))
class Solution(object):
def numMatchingSubseq(self, S, words):
"""
:type S: str
:type words: List[str]
:rtype: int
"""
from collections import defaultdict
dic = defaultdict(list)
for i, ch in enumerate(S): # 建哈希表
dic[ch].append(i)
res = 0
for word in words:
pre = -1
flag = True
for i, ch in enumerate(word):
l = dic[ch]
# 在l里找第一个比pre大的元素
idx = bisect.bisect(l, pre)
if idx == len(l):# 没找到
flag = False
break
pre = l[idx]
if flag:
res += 1
return res