题目描述:
给定字符串 s 和字符串数组 words, 返回 words[i] 中是s的子序列的单词个数 。
字符串的 子序列 是从原始字符串中生成的新字符串,可以从中删去一些字符(可以是none),而不改变其余字符的相对顺序。
例如, “ace” 是 “abcde” 的子序列。
解题思路:
方法一:分桶
题目中字符串 s 的数据规模最高达到 5×10^4 ,如果暴力枚举 words 中的每个字符串 w,判断其是否为 s 的子序列,很有可能会超时。
我们不妨将 words 中的所有单词根据首字母来分桶,即:把所有单词按照首字母分到 26 个桶中,每个桶中存储的是所有以该字母开头的所有单词。
然后我们从 s 的第一个字符开始遍历,假设当前字符为 ‘a’,我们从 ‘a’ 开头的桶中取出所有单词。对于取出的每个单词,如果此时单词长度为 1,说明该单词已经匹配完毕,我们将答案加 1;否则我们将单词的首字母去掉,然后放入下一个字母开头的桶中,比如对于单词 “acd”,去掉首字母 ‘a’ 后,我们将其放入 ‘c’ 开头的桶中。
遍历完 sss 后,我们就得到了答案。
代码演示:
class Solution:
def numMatchingSubseq(self, s: str, words: List[str]) -> int:
d = defaultdict(deque)
for i, w in enumerate(words):
d[w[0]].append((i, 0))
ans = 0
for c in s:
for _ in range(len(d[c])):
i, j = d[c].popleft()
j += 1
if j == len(words[i]):
ans += 1
else:
d[words[i][j]].append((i, j))
return ans