Given string S
and a dictionary of words words
, find the number of words[i]
that is a subsequence of S
.
Example : 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:
- All words in
words
andS
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]
.
-------------------------------------------------------------------------------
桶排序的思想:words中的词按照首字母分桶dic=defaultdict(list)。S中某一个字母c如果在dic中存在,都可以dic[c]中元素前进一步,也就是把dic[c]都清空,然后dic[nxt]记录新的下标。
写法一,记录下标:
from collections import defaultdict
class Solution:
def numMatchingSubseq(self, S, words):
dic = defaultdict(list)
len_arr = [0 for i in range(len(words))]
for idx,w in enumerate(words):
len_arr[idx] = len(w)
dic[w[0]].append((idx,0))
for c in S:
if c in dic:
pairs = dic.pop(c,[])
for idx,off in pairs:
nxt_ch = '$' if off+1 == len_arr[idx] else words[idx][off+1]
dic[nxt_ch].append((idx,off+1))
return len(dic['$'])
s = Solution()
print(s.numMatchingSubseq(S = "abcde", words = ["a", "bb", "acd", "ace"]))
写法二,使用iter和next,iter(某个list)结果是一个迭代子,next(it)返回it的当前元素,同时it移动到下一个:
def numMatchingSubseq(self, S, words):
waiting = collections.defaultdict(list)
for w in words:
waiting[w[0]].append(iter(w[1:]))
for c in S:
for it in waiting.pop(c, ()):
waiting[next(it, None)].append(it)
return len(waiting[None])