We are given two arrays A and B of words.  Each word is a string of lowercase letters.
Now, say that word b is a subset of word a if every letter in b occurs in a, including multiplicity.  For example, "wrr" is a subset of "warrior", but is not a subset of "world".
Now say a word a from A is universal if for every b in B, b is a subset of a. 
Return a list of all universal words in A.  You can return the words in any order.
 



Example 1:
Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["e","o"]
Output: ["facebook","google","leetcode"]


Example 2:
Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["l","e"]
Output: ["apple","google","leetcode"]


Example 3:
Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["e","oo"]
Output: ["facebook","google"]


Example 4:
Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["lo","eo"]
Output: ["google","leetcode"]


Example 5:
Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["ec","oc","ceo"]
Output: ["facebook","leetcode"]

 
Note:

1 <= A.length, B.length <= 10000
1 <= A[i].length, B[i].length <= 10
A[i] and B[i] consist only of lowercase letters.
All words in A[i] are unique: there isn't i != j with A[i] == A[j].

Difficulty: MEDIUM
Tags: String algorithms

Data structures
Skill types: Data structures

Starter code:
class Solution:
    def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
        

Solutions:
class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		s = set(A)
		letters_required = {}
		for i in B:
			for j in i:
				count = i.count(j)
				if j not in letters_required or count > letters_required[j]:
					letters_required[j] = count
		for i in A:
			for j in letters_required:
				if i.count(j) < letters_required[j]:
					s.remove(i)
					break
		return list(s)


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		ans = []
		word = {}
		for i in B:
			for j in i:
				if j not in word:
					word[j] = i.count(j)
				elif i.count(j) > word[j]:
					word[j] = i.count(j)
		for i in A:
			x = 0
			for k in word:
				if word[k] > i.count(k):
					x = 1
					break
			if x != 1:
				ans.append(i)
		return ans


from collections import Counter as di

class Solution:

	def wordSubsets(self, a: List[str], b: List[str]) -> List[str]:
		d = di()
		ans = list()
		for i in b:
			d2 = di(i)
			for (k, v) in d2.items():
				if d[k] < d2[k]:
					d[k] = v
		for i in a:
			if len(d - di(i)) == 0:
				ans.append(i)
		return ans


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		s = Counter()
		for b in B:
			s = s | Counter(b)
		words = []

		def is_universal(word: str):
			word_counts = Counter(word)
			if len(word) < len(s):
				return False
			for (k, v) in list(s.items()):
				if k not in word_counts:
					return False
				if word_counts[k] < v:
					return False
			return True
		for word in A:
			if is_universal(word):
				words.append(word)
		return words


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		subset = reduce(operator.or_, (Counter(w) for w in B))
		return [a for a in A if all((a.count(c) >= subset[c] for c in subset.keys()))]


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		h = {}
		for word in B:
			temp = Counter(word)
			for (key, value) in temp.items():
				if key not in h:
					h[key] = value
				else:
					h[key] = max(h[key], value)
		res = []
		for word in A:
			temp = Counter(word)
			suitable = True
			for (key, value) in h.items():
				if not (key in temp and value <= temp[key]):
					suitable = False
					break
			if suitable:
				res.append(word)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		if len(B) == 0:
			return A
		from collections import Counter
		cb = Counter()
		for b in B:
			for char in b:
				cb[char] = max(cb[char], b.count(char))
		res = []
		for a in A:
			if all((a.count(c) >= cb[c] for c in cb.keys())):
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		max_set = {}
		result = []
		for i in B:
			for char in i:
				if char not in max_set:
					max_set[char] = i.count(char)
				else:
					max_set[char] = max(i.count(char), max_set[char])
		for word in A:
			flag = True
			for char in max_set:
				if word.count(char) < max_set[char]:
					flag = False
					break
			if flag:
				result.append(word)
			else:
				pass
		return result


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		res = set()
		B_count = Counter()
		for b in B:
			word_count = Counter(b)
			for (c, v) in word_count.items():
				B_count[c] = max(B_count[c], v)
		for a in A:
			if len(B_count - Counter(a)) == 0:
				res.add(a)
		return list(res)


class Solution:

	def subset(self, a, b):
		base = [0] * 26
		i = 0
		while i < len(a) or i < len(b):
			if i < len(a) and i < len(b):
				base[ord(a[i]) - 97] -= 1
				base[ord(b[i]) - 97] += 1
			elif i < len(a):
				base[ord(a[i]) - 97] -= 1
			else:
				return False
			i += 1
		for c in base:
			if c > 0:
				return False
		return True

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		B = list(set(B))
		base = [0] * 26
		for b in B:
			cur = [0] * 26
			for c in b:
				cur[ord(c) - 97] += 1
			for i in range(len(base)):
				base[i] = max(base[i], cur[i])
		ret = []
		for a in A:
			cur = [0] * 26
			for c in a:
				cur[ord(c) - 97] += 1
			add = True
			for i in range(len(base)):
				if base[i] > cur[i]:
					add = False
					break
			if add:
				ret.append(a)
		return ret


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		ctr = collections.Counter()
		for word in B:
			ctr2 = collections.Counter(word)
			for (key, val) in ctr2.items():
				ctr[key] = max(val, ctr[key])
		ctr3 = collections.Counter()
		res = []
		for w in A:
			ctr3 = collections.Counter(w)
			newCtr = collections.Counter()
			for (key, val) in ctr3.items():
				if key in ctr:
					newCtr[key] = min(val, ctr[key])
			if newCtr == ctr:
				res.append(w)
		return res


from collections import defaultdict

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_dict = defaultdict(int)
		for word in B:
			curr = defaultdict(int)
			for char in word:
				curr[char] += 1
			for char in curr:
				b_dict[char] = max(b_dict[char], curr[char])
		universal = []
		for word in A:
			curr = defaultdict(int)
			for char in word:
				curr[char] += 1
			is_subset = True
			for char in b_dict:
				if char not in curr or curr[char] < b_dict[char]:
					is_subset = False
					break
			if is_subset:
				universal.append(word)
		return universal


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		cnt = collections.Counter
		bCnt = cnt()
		for b in B:
			bCnt |= cnt(b)
		return [a for a in A if not bCnt - cnt(a)]


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		(i, A2, seen) = (0, [], set())
		while i < len(A):
			if A[i] not in seen:
				seen.add(A[i])
				dct = {}
				for char in A[i]:
					if char in dct:
						dct[char] += 1
					else:
						dct[char] = 1
				A2.append(dct)
				i += 1
			else:
				A.pop(i)
		(i, seen) = (0, set())
		while i < len(B):
			if B[i] not in seen:
				seen.add(B[i])
				dct = {}
				for char in B[i]:
					if char in dct:
						dct[char] += 1
					else:
						dct[char] = 1
				B[i] = dct
				i += 1
			else:
				B.pop(i)
		while len(B) > 1:
			for key in B[1]:
				if key in B[0]:
					B[1][key] = max(B[1][key], B[0][key])
			for key in B[0]:
				if key not in B[1]:
					B[1][key] = B[0][key]
			B.pop(0)
		B_dct = B[0]
		(ans, A_len, B_len) = ([], len(A), len(B))
		for i in range(A_len):
			isSubset = True
			for key in B_dct:
				if key not in A2[i] or (key in A2[i] and B_dct[key] > A2[i][key]):
					isSubset = False
					break
			if isSubset:
				ans.append(A[i])
		return ans


import collections

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_cnt = collections.Counter()
		for b in B:
			b_cnt |= collections.Counter(b)
		res = []
		for a in A:
			if collections.Counter(a) & b_cnt == b_cnt:
				res.append(a)
		return res


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		subset = Counter()
		for b in B:
			for (k, v) in Counter(b).items():
				subset[k] = max(subset[k], v)
		result = filter(lambda a: True if not subset - Counter(a) else False, A)
		return list(result)


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		w1_set = {}
		for word in B:
			new_w1_set = {}
			for c in word:
				if c not in new_w1_set:
					new_w1_set[c] = 0
				new_w1_set[c] += 1
			for c in new_w1_set:
				if c not in w1_set:
					w1_set[c] = new_w1_set[c]
				else:
					w1_set[c] = max(w1_set[c], new_w1_set[c])
		output = []
		for word in A:
			w2_set = {}
			for c in word:
				if c not in w2_set:
					w2_set[c] = 0
				w2_set[c] += 1
			check = True
			for c in w1_set:
				if c not in w2_set or w1_set[c] > w2_set[c]:
					check = False
					break
			if check:
				output.append(word)
		return output


import collections

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def aggregate_b(B):
			max_occurences = collections.defaultdict(list)
			for subset in B:
				letter_count = collections.Counter(subset)
				for (letter, count) in list(letter_count.items()):
					if not max_occurences[letter] or count > max_occurences[letter]:
						max_occurences[letter] = count
			return max_occurences
		result = []
		max_letter_occurences = aggregate_b(B)
		for word in A:
			letter_count = max_letter_occurences.copy()
			for letter in word:
				if letter in letter_count:
					letter_count[letter] -= 1
					if letter_count[letter] == 0:
						del letter_count[letter]
			if not letter_count:
				result.append(word)
		return result


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		total_count_B = Counter()
		for s in B:
			total_count_B |= Counter(s)
		return [a for a in A if Counter(a) & total_count_B == total_count_B]


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_hash = {}
		ans = []
		for i in B:
			for j in set(i):
				if j in b_hash:
					b_hash[j] = max(i.count(j), b_hash[j])
				else:
					b_hash[j] = i.count(j)
		for wrd in A:
			new_b_hash = b_hash.copy()
			for i in set(wrd):
				if i in b_hash:
					new_b_hash[i] -= wrd.count(i)
			value_flag = True
			for i in list(new_b_hash.values()):
				if i > 0:
					value_flag = False
					break
			if value_flag:
				ans.append(wrd)
		return ans


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		universal_words = []
		required_counts = {}
		for pattern in B:
			for char in pattern:
				char_sum = sum((1 for i in pattern if i == char))
				if char not in required_counts or required_counts[char] < char_sum:
					required_counts[char] = char_sum
		print(required_counts)
		for word in A:
			universal = True
			for char in required_counts:
				char_count = sum((1 for i in word if i == char))
				if char_count < required_counts[char]:
					universal = False
			if universal:
				universal_words.append(word)
		return universal_words


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		lc = [0] * 26
		for b in B:
			for (c, count) in collections.Counter(b).items():
				i = ord(c) - ord('a')
				lc[i] = max(lc[i], count)
		ans = []
		for a in A:
			uni = True
			cter = collections.Counter(a)
			for (c, count) in zip(string.ascii_lowercase, lc):
				if count > cter[c]:
					uni = False
					break
			if uni:
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		answer = list()
		b_counter = collections.Counter()
		for word in B:
			counter = collections.Counter(word)
			for (letter, count) in counter.items():
				b_counter[letter] = max(b_counter[letter], count)
		for word in A:
			counter = collections.Counter(word)
			if all((l in counter and counter[l] >= count for (l, count) in b_counter.items())):
				answer.append(word)
		return answer


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		from collections import Counter
		freq = {word: Counter(word) for word in A}
		queries = {word: Counter(word) for word in B}
		query = {chr(i): max((queries[word].get(chr(i), 0) for word in queries)) for i in range(ord('a'), ord('z') + 1)}
		ans = set()
		for k in list(freq.keys()):
			flag = 1
			for ch in query:
				if query[ch] > freq[k].get(ch, 0):
					flag = 0
					break
			if flag:
				ans.add(k)
		return list(ans)


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		seen = set()
		freq_B = [0] * 26
		for word in B:
			if word not in seen:
				seen.add(word)
				freq_cur = [0] * 26
				for c in word:
					freq_cur[ord(c) - ord('a')] += 1
				for i in range(26):
					freq_B[i] = max(freq_B[i], freq_cur[i])
		ans = []
		for word in A:
			freq_A = [0] * 26
			for c in word:
				freq_A[ord(c) - ord('a')] += 1
			broke_early = False
			for i in range(26):
				if freq_A[i] < freq_B[i]:
					broke_early = True
					break
			if broke_early:
				continue
			ans += [word]
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_union_ctr = Counter()
		for b_element in B:
			b_union_ctr |= Counter(b_element)
		output = []
		for a_element in A:
			a_count = Counter(a_element)
			if len(b_union_ctr - a_count) == 0:
				output.append(a_element)
		return output


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		count = collections.Counter()
		for b in B:
			count |= collections.Counter(b)
		return [a for a in A if Counter(a) & count == count]


from functools import reduce

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		cntB = [Counter(b) for b in B]
		sumB = reduce(lambda x, y: x | y, cntB)
		ans = []
		for a in A:
			cnt = Counter(a)
			if all((sumB[s] <= cnt[s] for s in sumB)):
				ans.append(a)
		return ans


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		if len(B) == 0:
			return []
		ans = []
		ca = [Counter(a) for a in A]
		cb = Counter(B[0])
		for i in range(1, len(B)):
			lb = Counter(B[i])
			for c in lb:
				cb[c] = max(cb[c], lb[c])
		for i in range(len(A)):
			isUniv = True
			if len(cb - ca[i]) > 0:
				continue
			ans.append(A[i])
		return ans


class Solution:

	def issubset(self, s: str, t: str) -> bool:
		dic = dict()
		for i in range(len(t)):
			dic[t[i]] = dic.get(t[i], 0) + 1
		result = True
		i = 0
		while i < len(s) and result:
			if s[i] not in list(dic.keys()) or dic[s[i]] < 1:
				result = False
			else:
				dic[s[i]] -= 1
				i += 1
		return result

	def joining(self, B: List[str]) -> str:
		result = dict()
		for i in range(len(B)):
			word = B[i]
			temp = dict()
			for j in range(len(word)):
				temp[word[j]] = temp.get(word[j], 0) + 1
			for (k, v) in list(temp.items()):
				if k not in list(result.keys()) or result[k] < v:
					result[k] = v
		res = ''
		for (k, v) in list(result.items()):
			res += k * v
		return res

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		res = []
		union = self.joining(B)
		for word in A:
			if self.issubset(union, word) == True:
				res.append(word)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		maxcb = Counter()
		for b in B:
			maxcb |= Counter(b)
		return [a for a in A if Counter(a) & maxcb == maxcb]


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		dic = {}
		out = []
		for word in B:
			dicWord = {}
			for letter in word:
				if not letter in dicWord:
					dicWord[letter] = 1
				else:
					dicWord[letter] += 1
			for letter in dicWord:
				if not letter in dic:
					dic[letter] = dicWord[letter]
				else:
					dic[letter] = max(dic[letter], dicWord[letter])
		for word in A:
			dicWord = {}
			universal = True
			for letter in word:
				if letter in dicWord:
					dicWord[letter] += 1
				else:
					dicWord[letter] = 1
			for letter in dic:
				if not letter in dicWord:
					universal = False
					break
				if dic[letter] > dicWord[letter]:
					universal = False
					break
			if not universal:
				continue
			else:
				out += [word]
		return out


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		need = Counter()
		for word in B:
			word_count = Counter(word)
			for (k, v) in list(word_count.items()):
				need[k] = max(need[k], v)

		def is_subset(word):
			word_count = Counter(word)
			needed = need.copy()
			for c in need:
				word_count[c] -= needed[c]
				if word_count[c] < 0:
					return False
			return True
		res = []
		for word in A:
			if is_subset(word):
				res.append(word)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		res = []
		max_b = [0] * 26
		for i in range(len(B)):
			local_b = [0] * 26
			for c in B[i]:
				local_b[ord(c) - 97] += 1
			for i in range(26):
				max_b[i] = max(max_b[i], local_b[i])
		for i in range(len(A)):
			local_a = [0] * 26
			for c in A[i]:
				local_a[ord(c) - 97] += 1
			for k in range(26):
				if local_a[k] < max_b[k]:
					break
				if k == 25:
					res.append(A[i])
		return res


class Solution:

	def wordSubsets(self, A: 'List[str]', B: 'List[str]') -> 'List[str]':

		def count(word):
			ans = [0] * 26
			for c in word:
				ans[ord(c) - ord('a')] += 1
			return ans
		bmax = [0] * 26
		for b in B:
			ls = count(b)
			for i in range(26):
				bmax[i] = max(bmax[i], ls[i])
		ans = []
		for a in A:
			ls = count(a)
			for i in range(26):
				if ls[i] < bmax[i]:
					break
			else:
				ans.append(a)
		return ans


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		c = Counter()
		for b in B:
			c = c | Counter(b)
		return [a for a in A if Counter(a) & c == c]


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_representation = [0] * 26

		def str2list(s):
			li = [0] * 26
			for c in s:
				li[ord(c) - ord('a')] += 1
			return li

		def is_greater(li1, li2):
			for i in range(26):
				if li1[i] < li2[i]:
					return False
			return True
		for s in B:
			b_representation = [max(tmp1, tmp2) for (tmp1, tmp2) in zip(b_representation, str2list(s))]
		res = []
		for s in A:
			if is_greater(str2list(s), b_representation):
				res.append(s)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		ret = []
		bx = Counter()
		for ib in B:
			bx |= Counter(ib)
		for ia in A:
			cx = Counter(ia) & bx
			if cx == bx:
				ret.append(ia)
		return ret


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		counter = [0] * 26
		res = []
		for b in B:
			temp = [0] * 26
			for c in b:
				temp[ord(c) - ord('a')] += 1
			for i in range(26):
				counter[i] = max(counter[i], temp[i])
		for a in A:
			temp = [0] * 26
			for c in a:
				k = ord(c) - ord('a')
				temp[k] += 1
			for i in range(26):
				if temp[i] < counter[i]:
					break
			else:
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		universal = Counter()
		for b in B:
			universal |= Counter(b)
		ans = []
		for a in A:
			c = Counter(a)
			c.subtract(universal)
			if all((v >= 0 for v in c.values())):
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		cnt = [0] * 26
		for b in B:
			cnt1 = [0] * 26
			for c in b:
				cnt1[ord(c) - 97] += 1
			for (i, j) in enumerate(cnt1):
				cnt[i] = max(cnt[i], j)
		result = []
		for a in A:
			cnt1 = [0] * 26
			for c in a:
				cnt1[ord(c) - 97] += 1
			if all((j <= cnt1[i] for (i, j) in enumerate(cnt))):
				result.append(a)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		temp = {}
		require = {}
		universal = []
		for b in B:
			temp.clear()
			for c in b:
				if c in temp:
					temp[c] += 1
				else:
					temp[c] = 1
			for k in temp:
				if k not in require or require[k] < temp[k]:
					require[k] = temp[k]
		for a in A:
			toAdd = True
			temp.clear()
			for c in a:
				if c in temp:
					temp[c] += 1
				else:
					temp[c] = 1
			for k in require:
				if k not in temp or require[k] > temp[k]:
					toAdd = False
					break
			if toAdd:
				universal.append(a)
		return universal


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		res = []
		bwdict = Counter(B[0])
		for bw in B[1:]:
			tmpCounter = Counter(bw)
			for (key, val) in list(tmpCounter.items()):
				wcnt = bwdict.get(key, -1)
				if val > wcnt:
					bwdict[key] = val
		print(bwdict)
		for word in A:
			tmpW = (word + '.')[:-1]
			wdict = Counter(word)
			isSub = []
			for (key, val) in list(bwdict.items()):
				wcnt = wdict.get(key, -1)
				if val <= wcnt:
					isSub.append(True)
				else:
					isSub.append(False)
			if all(isSub):
				res.append(word)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		if not A:
			return []
		word_map_B = self.createMapWordB(B)
		res = []
		for word in A:
			if self.searchWord(word, word_map_B):
				res.append(word)
		return res

	def createMapWordB(self, B):
		max_B = [0] * 26
		for b in B:
			temp_B = self.createSingleWordCount(b)
			for i in range(26):
				max_B[i] = max(max_B[i], temp_B[i])
		return max_B

	def createSingleWordCount(self, word):
		res = [0] * 26
		for c in word:
			idx = ord(c) - ord('a')
			res[idx] += 1
		return res

	def searchWord(self, word, max_B):
		word_count = self.createSingleWordCount(word)
		for i in range(26):
			if word_count[i] < max_B[i]:
				return False
		return True


from functools import reduce

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		alphabet = reduce(lambda x, y: Counter(y) | x, B, Counter())
		return [a for a in A if Counter(a) & alphabet == alphabet]


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		res = []
		b_word = [0] * 26
		for word in B:
			for (idx, count) in enumerate(self.create_char_set(word)):
				b_word[idx] = max(b_word[idx], count)
		for word in A:
			a_word = self.create_char_set(word)
			idx = 0
			while idx < len(b_word) and a_word[idx] >= b_word[idx]:
				idx += 1
			if idx == len(b_word):
				res.append(word)
		return res

	def create_char_set(self, word):
		char_set = [0] * 26
		for char in word:
			char_set[ord(char) - ord('a')] += 1
		return char_set


class Solution(object):

	def wordSubsets(self, A, B):

		def count(word):
			ans = [0] * 26
			for letter in word:
				ans[ord(letter) - ord('a')] += 1
			return ans
		bmax = [0] * 26
		for b in B:
			for (i, c) in enumerate(count(b)):
				bmax[i] = max(bmax[i], c)
		ans = []
		for a in A:
			if all((x >= y for (x, y) in zip(count(a), bmax))):
				ans.append(a)
		return ans


from collections import defaultdict

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		result = []
		if not A:
			return result
		if not B:
			return A
		C = []
		for j in B:
			d = [0] * 26
			for ch in j:
				d[ord(ch) - ord('a')] += 1
			C.append(d)
		l = [0] * 26
		for j in C:
			for i in range(26):
				l[i] = max(l[i], j[i])
		for i in A:
			d = list(l)
			for ch in i:
				if d[ord(ch) - ord('a')] > 0:
					d[ord(ch) - ord('a')] -= 1
			if sum(d) == 0:
				result.append(i)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		dic = {}
		for b in B:
			for char in b:
				dic[char] = max(dic.get(char, 0), b.count(char))
		res = []
		for a in A:
			if all((a.count(k) >= dic[k] for k in dic)):
				res.append(a)
		return res


class Solution:

	def count(self, word):
		res = [0] * 26
		for item in word:
			tmp = ord(item) - ord('a')
			res[tmp] += 1
		return res

	def satisfy(self, item, bmax):
		tmp = self.count(item)
		for i in range(26):
			if tmp[i] < bmax[i]:
				return False
		return True

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		bmax = [0] * 26
		for item in B:
			for (index, val) in enumerate(self.count(item)):
				bmax[index] = max(bmax[index], val)
		res = []
		for item in A:
			if self.satisfy(item, bmax):
				res.append(item)
		return res


class Solution(object):

	def wordSubsets(self, A, B):

		def count(word):
			res = [0] * 26
			for i in word:
				res[ord(i) - ord('a')] += 1
			return res
		b_max = [0] * 26
		for b in B:
			bb = count(b)
			for w in range(26):
				b_max[w] = max(b_max[w], bb[w])
		ans = []
		for a in A:
			if all((x >= y for (x, y) in zip(count(a), b_max))):
				ans.append(a)
		return ans


class Solution:

	def getCharFrequency(self, word):
		f = [0] * 26
		for ch in word:
			f[ord(ch) - ord('a')] += 1
		return f

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		result = []
		max_freq = [0] * 26
		for i in range(len(B)):
			curr_freq = self.getCharFrequency(B[i])
			for j in range(26):
				max_freq[j] = max(max_freq[j], curr_freq[j])
		for i in range(len(A)):
			curr_freq = self.getCharFrequency(A[i])
			valid = True
			for j in range(26):
				if max_freq[j] > curr_freq[j]:
					valid = False
					break
			if valid:
				result.append(A[i])
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def count(s):
			cnt = [0] * 26
			for c in s:
				cnt[ord(c) - ord('a')] += 1
			return cnt
		cnt = [0] * 26
		for b in B:
			bcnt = count(b)
			for (i, c) in enumerate(bcnt):
				cnt[i] = max(cnt[i], c)
		ans = []
		for a in A:
			acnt = count(a)
			if all((x >= y for (x, y) in zip(acnt, cnt))):
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		d = {}
		for a in A:
			d[a] = Counter(a)
		cd = defaultdict(int)
		for b in B:
			for i in Counter(b):
				cd[i] = max(cd[i], Counter(b)[i])
		ret = []
		for k in d:
			t = True
			for c in cd:
				if c not in k or d[k][c] < cd[c]:
					t = False
					break
			if t:
				ret.append(k)
		return ret


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		subset = {}
		for b in B:
			for char in b:
				subset[char] = max(subset.get(char, 0), b.count(char))
		return [a for a in A if all((a.count(c) >= subset[c] for c in subset.keys()))]


from collections import Counter

class Solution:

	def wordSubsets(self, A, B):
		count = collections.Counter()
		for b in B:
			count = count | collections.Counter(b)
		return [a for a in A if Counter(a) & count == count]


import collections

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		dp = [0] * 26
		for b in B:
			dp = [max(i, j) for (i, j) in zip(dp, self.bow(b))]
		print(dp)
		res = []
		for a in A:
			if not any([al < bl for (al, bl) in zip(self.bow(a), dp)]):
				res.append(a)
		return res

	def bow(self, text):
		d = [0] * 26
		for l in text:
			d[ord(l) - ord('a')] += 1
		return d


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		cover = [0] * 26
		for i in range(len(B)):
			max_cnt = [0] * 26
			for c in B[i]:
				max_cnt[ord(c) - ord('a')] += 1
			cover = [max(x, y) for (x, y) in zip(cover, max_cnt)]
		res = []
		for i in range(len(A)):
			cnt = [0] * 26
			for c in A[i]:
				cnt[ord(c) - ord('a')] += 1
			if all([x >= y for (x, y) in zip(cnt, cover)]):
				res.append(A[i])
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		A_dict = []
		B_dict = {}
		ans = []
		for ww in A:
			temp = {}
			for ele in ww:
				if ele in temp:
					temp[ele] += 1
				else:
					temp[ele] = 1
			A_dict.append(temp)
		for ww in B:
			temp = {}
			for ele in ww:
				if ele in temp:
					temp[ele] += 1
				else:
					temp[ele] = 1
			for (key, cnt) in temp.items():
				if key in B_dict:
					B_dict[key] = max(cnt, B_dict[key])
				else:
					B_dict[key] = cnt
		for (ind, ele) in enumerate(A_dict):
			cur_dict = ele
			flag = True
			for (key, cnt) in B_dict.items():
				if key not in cur_dict or cur_dict[key] < cnt:
					flag = False
					break
			if flag:
				ans.append(A[ind])
		return ans


from functools import reduce

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		c_b = reduce(operator.or_, (Counter(w) for w in B))
		return [a for a in A if not c_b - Counter(a)]


from collections import defaultdict

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		bMap = defaultdict(int)
		ans = []
		maxB = [0] * 26
		for b in B:
			m = self.count(b)
			for i in range(len(m)):
				maxB[i] = max(maxB[i], m[i])
		for a in A:
			aMap = self.count(a)
			c = 0
			for i in range(len(aMap)):
				if aMap[i] >= maxB[i]:
					c += 1
			if c == 26:
				ans.append(a)
		return ans

	def count(self, arr):
		ans = [0] * 26
		for ch in arr:
			ans[ord(ch) - ord('a')] += 1
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def countLetter(s):
			res = [0] * 26
			for c in s:
				res[ord(c) - ord('a')] += 1
			return res
		b_count = [0] * 26
		for b in B:
			for (i, c) in enumerate(countLetter(b)):
				b_count[i] = max(b_count[i], c)
		return [x for x in A if all([x >= y for (x, y) in zip(countLetter(x), b_count)])]


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		counter = [0] * 26
		for word in B:
			tmp = [0] * 26
			for c in map(lambda x: ord(x) - ord('a'), word):
				tmp[c] += 1
			for c in range(26):
				counter[c] = max(counter[c], tmp[c])
		ans = []
		for word in A:
			tmp = [0] * 26
			for c in map(lambda x: ord(x) - ord('a'), word):
				tmp[c] += 1
			if all((counter[c] <= tmp[c] for c in range(26))):
				ans.append(word)
		return ans


import collections

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		A = [(a, collections.Counter(a)) for a in A]
		newB = {}
		for b in B:
			for (x, c) in collections.Counter(b).items():
				newB[x] = c if x not in newB else max(newB[x], c)
		B = newB
		return [a for (a, counts) in A if all((counts[x] >= c for (x, c) in B.items()))]


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		arr1 = []
		arr2 = []
		for x in A:
			arr1.append(collections.Counter(x))
		dic = collections.defaultdict(int)
		for y in B:
			t = collections.Counter(y)
			for c in t:
				dic[c] = max(dic[c], t[c])
		res = []

		def comp(i):
			for c in dic:
				if arr1[i][c] < dic[c]:
					return False
			return True
		for i in range(len(A)):
			if comp(i):
				res.append(A[i])
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		LETTERS = 26
		base = ord('a')
		bCounts = [0 for _ in range(LETTERS)]
		for word in B:
			currCounts = [0 for _ in range(LETTERS)]
			for c in word:
				currCounts[ord(c) - base] += 1
			for i in range(LETTERS):
				bCounts[i] = max(currCounts[i], bCounts[i])
		result = []
		for word in A:
			currCounts = [0 for _ in range(LETTERS)]
			for c in word:
				currCounts[ord(c) - base] += 1
			valid = True
			for i in range(LETTERS):
				if currCounts[i] < bCounts[i]:
					valid = False
					break
			if valid:
				result.append(word)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		m = {}
		ret = []
		for b in B:
			each = {}
			for i in range(len(b)):
				each[b[i]] = each[b[i]] + 1 if b[i] in each else 1
			for k in each:
				if not k in m or m[k] < each[k]:
					m[k] = each[k]
		for a in A:
			each = {}
			for i in range(len(a)):
				each[a[i]] = each[a[i]] + 1 if a[i] in each else 1
			isAdding = True
			for k in m:
				if not k in each or each[k] < m[k]:
					isAdding = False
					break
			if isAdding:
				ret.append(a)
		return ret


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		cnt = Counter()
		for i in B:
			cnt |= Counter(i)
		res = []
		for i in A:
			if not cnt - Counter(i):
				res.append(i)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def count(word):
			ans = [0] * 26
			for c in word:
				ans[ord(c) - ord('a')] += 1
			return ans
		B_dict = [0] * 26
		for b in B:
			for (i, c) in enumerate(count(b)):
				B_dict[i] = max(B_dict[i], c)
		ans = []
		for a in A:
			a_dict = count(a)
			flag = True
			for (i, c) in enumerate(count(a)):
				if c < B_dict[i]:
					flag = False
					break
			if flag:
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		A_counter = [Counter(a) for a in A]
		B_counter = [Counter(b) for b in B]
		b_merged = Counter()
		for chr_ in string.ascii_lowercase:
			b_merged[chr_] = max([bc[chr_] for bc in B_counter])

		def is_subset(ac, bc):
			for chr_ in string.ascii_lowercase:
				if ac[chr_] < bc[chr_]:
					return False
			return True
		ans = []
		for (i, ac) in enumerate(A_counter):
			if is_subset(ac, b_merged):
				ans.append(A[i])
		return ans


from functools import reduce

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		c_a = [Counter(w) for w in A]
		c_b = reduce(lambda x, y: x | y, [Counter(w) for w in B])
		return [word for (i, word) in enumerate(A) if not c_b - c_a[i]]


from functools import reduce

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_cnt = reduce(lambda a, b: Counter(a) | Counter(b), B)
		a_cnt = Counter()
		result = []
		for word in A:
			for w in word:
				if w in b_cnt:
					a_cnt[w] += 1
			if not b_cnt - a_cnt:
				result.append(word)
			a_cnt.clear()
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		(ans, char_count, size_t) = (list(), Counter(), len(A))
		(T_A, T_B) = ([Counter(a) for a in A], [Counter(b) for b in B])
		for k in T_B:
			for c in k:
				if k[c] > char_count[c]:
					char_count[c] = k[c]
		for i in range(len(T_A)):
			if not char_count - T_A[i] == {}:
				continue
			ans.append(A[i])
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		output_list = []

		def count(word):
			res = [0] * 26
			for ch in word:
				pos = ord(ch) - ord('a')
				res[pos] = res[pos] + 1
			return res
		b_max = [0] * 26
		for b in B:
			res_b = count(b)
			for i in range(26):
				b_max[i] = max(b_max[i], res_b[i])
		for a in A:
			if all((x >= y for (x, y) in zip(count(a), b_max))):
				output_list.append(a)
		return output_list


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_counts = {}
		for word in B:
			word_counts = {}
			for letter in word:
				if letter in word_counts:
					word_counts[letter] += 1
				else:
					word_counts[letter] = 1
			for letter in word_counts:
				if letter in b_counts:
					b_counts[letter] = max(b_counts[letter], word_counts[letter])
				else:
					b_counts[letter] = word_counts[letter]
		result = []
		for word in A:
			a_counts = {}
			for letter in word:
				if letter in a_counts:
					a_counts[letter] += 1
				else:
					a_counts[letter] = 1
			superset = True
			for key in b_counts:
				if key not in a_counts or b_counts[key] > a_counts[key]:
					superset = False
					break
			if superset:
				result.append(word)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_cnt = reduce(lambda a, b: Counter(a) | Counter(b), B)
		return [a for a in A if not b_cnt - Counter(a)]


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def conv(w):
			sol = [0 for _ in range(26)]
			for c in w:
				sol[ord(c) - ord('a')] += 1
			return sol
		bmax = [0 for _ in range(26)]
		for wb in B:
			for (idx, cnt) in enumerate(conv(wb)):
				bmax[idx] = max(bmax[idx], cnt)
		sol = []
		for wa in A:
			if all((a >= b for (a, b) in zip(conv(wa), bmax))):
				sol.append(wa)
		return sol


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		universal_word = Counter()
		for b in B:
			universal_word |= Counter(b)
		result = []
		for a in A:
			if not universal_word - Counter(a):
				result.append(a)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		m = {}
		for i in range(26):
			letter = chr(ord('a') + i)
			m[letter] = 0
			for w in B:
				ct_curr_l = w.count(letter)
				m[letter] = max(m[letter], ct_curr_l)
		res = []
		for w in A:
			A_m = {}
			rt = True
			for l in w:
				if not l in A_m:
					A_m[l] = 0
				A_m[l] += 1
			for k in m:
				if m[k] > 0 and (k not in A_m or A_m[k] < m[k]):
					rt = False
			if rt == True:
				res.append(w)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def counter(c):
			listed = [0] * 26
			for i in c:
				x = ord(i) - 97
				listed[x] += 1
			return listed
		blist = [0] * 26
		for b in B:
			temp_list = counter(b)
			for i in range(0, 26):
				blist[i] = max(blist[i], temp_list[i])
		listed = blist
		l = []
		for a in A:
			temp_list = counter(a)
			universal = True
			for i in range(0, 26):
				if listed[i] > temp_list[i]:
					universal = False
			if universal:
				l.append(a)
		return l


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		if len(B) == 0:
			return A
		from collections import Counter
		cb = Counter(B[0])
		for i in range(1, len(B)):
			c = Counter(B[i])
			for ch in c.keys():
				cb[ch] = max(cb[ch], c[ch])
		res = []
		for a in A:
			add = True
			ca = Counter(a)
			for keyB in cb.keys():
				if keyB not in ca or cb[keyB] > ca[keyB]:
					add = False
			if add:
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		output_list = []

		def count(word):
			res = [0] * 26
			for ch in word:
				pos = ord(ch) - ord('a')
				res[pos] = res[pos] + 1
			return res
		b_max = [0] * 26
		for b in B:
			res_b = count(b)
			for i in range(26):
				b_max[i] = max(b_max[i], res_b[i])
		for a in A:
			res_a = count(a)
			for i in range(26):
				if b_max[i] > res_a[i]:
					break
				if i == 25:
					output_list.append(a)
		return output_list


def f(c):
	return ord(c) - ord('a')

class Solution:

	def wordSubsets(self, A, B):

		def isSubSet(coverA, coverB):
			for i in range(26):
				if coverA[i] < coverB[i]:
					return False
			return True
		coverB = [0] * 26
		for b in B:
			cover = [0] * 26
			for c in b:
				cover[f(c)] += 1
			for i in range(26):
				coverB[i] = max(coverB[i], cover[i])
		res = []
		for a in A:
			coverA = [0] * 26
			for c in a:
				coverA[f(c)] += 1
			if isSubSet(coverA, coverB):
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		letters = 'abcdefghijklmnopqrstuvwxyz'
		u = {c: 0 for c in letters}
		for w in B:
			for (c, f) in list(Counter(w).items()):
				u[c] = max(u[c], f)
		res = []
		for w in A:
			wc = Counter(w)
			if all((f <= wc[c] for (c, f) in list(u.items()))):
				res.append(w)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def count(s):
			alpha = [0] * 26
			for w in s:
				alpha[ord(w) - ord('a')] += 1
			return tuple(alpha)

		def compare(a, b):
			for i in range(26):
				if b[i] > a[i]:
					return False
			return True
		Acount = [count(a) for a in A]
		Bcount = [0] * 26
		for b in B:
			tmp = count(b)
			for i in range(26):
				Bcount[i] = max(Bcount[i], tmp[i])
		Bcount = tuple(Bcount)
		res = []
		for i in range(len(Acount)):
			if all((Acount[i][j] >= Bcount[j] for j in range(26))):
				res.append(A[i])
		return res


class Solution:

	def compare(self, d, d1):
		for i in d:
			if i not in d1 or d[i] > d1[i]:
				return False
		return True

	def wordSubsets(self, a: List[str], b: List[str]) -> List[str]:
		bgroup = {}
		for i in b:
			d = {}
			for j in i:
				if j in d:
					d[j] += 1
				else:
					d[j] = 1
			for j in d:
				if j not in bgroup:
					bgroup[j] = d[j]
				else:
					bgroup[j] = max(bgroup[j], d[j])
		ans = []
		for i in a:
			d1 = {}
			for j in i:
				if j in d1:
					d1[j] += 1
				else:
					d1[j] = 1
			if self.compare(bgroup, d1):
				ans.append(i)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		B_dt = collections.Counter(B[0])
		for b in B[1:]:
			B_dt = B_dt | collections.Counter(b)
		ans = []
		for a in A:
			if collections.Counter(a) & B_dt == B_dt:
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def freq(s):
			dp = [0 for _ in range(26)]
			for i in s:
				dp[ord(i) - ord('a')] += 1
			return dp
		arr = [0 for _ in range(26)]
		for b in B:
			for (i, j) in enumerate(freq(b)):
				arr[i] = max(arr[i], j)
		ans = []
		for a in A:
			flag = 1
			for (i, j) in enumerate(freq(a)):
				if arr[i] > j:
					flag = 0
			if flag:
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		superword = [0] * 26
		result = []
		for word in B:
			current = [0] * 26
			for ch in word:
				i = ord(ch) - ord('a')
				current[i] += 1
			for i in range(26):
				superword[i] = max(superword[i], current[i])
		for word in A:
			current = [0] * 26
			for ch in word:
				i = ord(ch) - ord('a')
				current[i] += 1
			found = True
			for i in range(26):
				if superword[i] > current[i]:
					found = False
					break
			if found == True:
				result.append(word)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		max_count = {}
		for string in B:
			char_count = {}
			for ch in string:
				char_count[ch] = char_count.get(ch, 0) + 1
			for ch in char_count:
				if ch not in max_count:
					max_count[ch] = 0
				max_count[ch] = max(max_count[ch], char_count[ch])
		print(max_count)
		res = []
		for string in A:
			char_count = {}
			for ch in string:
				char_count[ch] = char_count.get(ch, 0) + 1
			uni = True
			for key in max_count:
				if key not in char_count or max_count[key] > char_count[key]:
					uni = False
					break
			if uni:
				res.append(string)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_union = {}
		for b in B:
			chars = {}
			for c in b:
				chars[c] = chars.get(c, 0) + 1
			for c in chars:
				b_union[c] = max(b_union.get(c, 0), chars[c])
		res = []
		for a in A:
			chars = {}
			for c in a:
				chars[c] = chars.get(c, 0) + 1
			isUniversal = True
			for c in b_union:
				if not c in chars or b_union[c] > chars[c]:
					isUniversal = False
					break
			if isUniversal:
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		d = defaultdict(int)
		for i in B:
			for j in set(i):
				d[j] = max(i.count(j), d[j])
		l = []
		for i in A:
			if all((d[j] <= i.count(j) for j in list(d.keys()))):
				l.append(i)
		return l


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		if not B:
			return A
		mapB = [0] * 26
		B = list(set(B))
		for b in B:
			if not b:
				continue
			counter = collections.Counter(b)
			for k in b:
				index = ord(k) - ord('a')
				if counter[k] > mapB[index]:
					mapB[index] = counter[k]
		print(mapB)
		res = []
		for a in A:
			temp = mapB[:]
			for c in a:
				i = ord(c) - ord('a')
				if temp[i] > 0:
					temp[i] -= 1
			if sum(temp) == 0:
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		uni = []
		B_set = set(''.join(B))
		B_hist = {b_i: [max([b.count(b_i) for b in B]), -1] for b_i in B_set}
		for a in A:
			occurances_b = 0
			for b_i in B_set:
				occurances_b_i = 0
				stop = False
				B_hist[b_i][1] = -1
				for j in range(B_hist[b_i][0]):
					B_hist[b_i][1] = a.find(b_i, B_hist[b_i][1] + 1)
					if B_hist[b_i][1] == -1:
						stop = True
						break
					else:
						occurances_b_i += 1
				if stop == True:
					break
				if occurances_b_i == B_hist[b_i][0]:
					occurances_b += 1
			if occurances_b == len(B_set):
				uni.append(a)
		return uni


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		max_count = {}
		for string in B:
			char_count = {}
			for ch in string:
				char_count[ch] = char_count.get(ch, 0) + 1
			for ch in char_count:
				if ch not in max_count:
					max_count[ch] = 0
				max_count[ch] = max(max_count[ch], char_count[ch])
		print(max_count)
		res = []
		for string in A:
			char_count = {}
			for ch in string:
				char_count[ch] = char_count.get(ch, 0) + 1
			ctr = 0
			for key in max_count:
				if key in char_count and max_count[key] <= char_count[key]:
					ctr += 1
				else:
					break
			if ctr == len(max_count):
				res.append(string)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		ans = []
		wordCountA = [self.genWordCount(word) for word in A]
		wordCountB = [self.genWordCount(word) for word in B]
		reducedWordB = {}
		for wordDict in wordCountB:
			for (key, val) in wordDict.items():
				reducedWordB[key] = max(reducedWordB[key], val) if key in reducedWordB else val
		for i in range(len(A)):
			if self.isSubset(wordCountA[i], reducedWordB):
				ans.append(A[i])
		return ans

	def genWordCount(self, word):
		wordCount = {}
		for c in word:
			if c in wordCount:
				wordCount[c] += 1
			else:
				wordCount[c] = 1
		return wordCount

	def isSubset(self, dictA, dictB):
		for (key, val) in dictB.items():
			if key not in dictA or dictA[key] < val:
				return False
		return True


from collections import defaultdict

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		ch2cnt = defaultdict(int)
		for b in B:
			tmp_cnt = defaultdict(int)
			for ch in b:
				tmp_cnt[ch] += 1
			for (k, v) in tmp_cnt.items():
				ch2cnt[k] = max(ch2cnt[k], v)
		res = []
		for a in A:
			tmp_dict = dict(ch2cnt)
			for ch in a:
				if ch in tmp_dict:
					tmp_dict[ch] -= 1
					if tmp_dict[ch] == 0:
						tmp_dict.pop(ch)
			if len(tmp_dict) == 0:
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		universe = defaultdict(int)
		for b in B:
			bCount = defaultdict(int)
			for letter in b:
				bCount[letter] += 1
			for key in bCount:
				universe[key] = max(universe[key], bCount[key])
		result = []
		for a in A:
			aCount = defaultdict(int)
			for letter in a:
				aCount[letter] += 1
			isUni = True
			for letter in universe:
				if universe[letter] > aCount[letter]:
					isUni = False
					break
				else:
					pass
			if isUni:
				result.append(a)
		return result


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		minFreq = {}
		for word in B:
			freq = Counter(word)
			for (key, value) in list(freq.items()):
				if key in minFreq:
					if value > minFreq[key]:
						minFreq[key] = value
				else:
					minFreq[key] = value
		ans = []
		for word in A:
			c = minFreq.copy()
			flag = True
			for i in range(len(word)):
				if word[i] in c:
					c[word[i]] -= 1
			for value in list(c.values()):
				if value > 0:
					flag = False
					break
			if flag:
				ans.append(word)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def get_b_map(words):
			res = collections.defaultdict(int)
			for word in words:
				temp_dict = collections.defaultdict(int)
				for char in word:
					temp_dict[char] += 1
					res[char] = max(res[char], temp_dict[char])
			return res
		b_map = get_b_map(B)

		def contains(word, b_map):
			same_freqs = 0
			temp_dict = collections.defaultdict(int)
			for char in word:
				if char not in b_map:
					continue
				temp_dict[char] += 1
				if temp_dict[char] == b_map[char]:
					same_freqs += 1
			return same_freqs == len(b_map)
		res = []
		for word in A:
			if contains(word, b_map):
				res.append(word)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		d = {}
		for e in B:
			tmp = {}
			for c in e:
				if c not in tmp:
					tmp.update({c: 1})
				else:
					tmp[c] += 1
			if not d or not tmp:
				d.update(tmp)
			else:
				for (k, v) in list(tmp.items()):
					if k in d:
						if v > d[k]:
							d[k] = v
					else:
						d.update({k: v})
		if not d:
			return A
		ans = []
		for a in A:
			tmp = {}
			f = True
			for e in a:
				if e not in tmp:
					tmp.update({e: 1})
				else:
					tmp[e] += 1
			for (k, v) in list(d.items()):
				if k in tmp:
					if v <= tmp[k]:
						pass
					else:
						f = False
						break
				else:
					f = False
					break
			if f:
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		s = set(A)
		letters_required = {}
		for b in B:
			for c in b:
				count = b.count(c)
				if c not in letters_required or count > letters_required[c]:
					letters_required[c] = count
		for a in A:
			for lr in letters_required:
				if a.count(lr) < letters_required[lr]:
					s.remove(a)
					break
		return list(s)


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		bLets = collections.Counter()
		for w in B:
			for (l, cnt) in collections.Counter(w).items():
				if cnt > bLets[l]:
					bLets[l] = cnt
		bTotal = sum(bLets.values())
		bLets = bLets.most_common()
		result = []
		aLets = collections.Counter()
		for w in A:
			if len(w) >= bTotal:
				aLets.update(w)
				for (l, cnt) in bLets:
					if cnt > aLets[l]:
						break
				else:
					result.append(w)
				aLets.clear()
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def getFrequency(s):
			d = {}
			for l in s:
				d[l] = d.get(l, 0) + 1
			return d
		main = {}
		for b in B:
			f = getFrequency(b)
			for k in f.keys():
				main[k] = max(main.get(k, 0), f[k])
		out = []
		for a in A:
			leto = getFrequency(a)
			cont = False
			for k in main.keys():
				if leto.get(k, 0) < main[k]:
					cont = True
					break
			if not cont:
				out.append(a)
		return out


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		dctB = {}
		for word in B:
			dct = {}
			for ch in word:
				cnt = dct.get(ch)
				dct[ch] = 1 if not cnt else dct[ch] + 1
			for key in dct:
				cnt = dctB.get(key)
				dctB[key] = dct[key] if not cnt else max(cnt, dct[key])
		res = []
		for word in A:
			dct = {}
			univ = True
			for ch in word:
				cnt = dct.get(ch)
				dct[ch] = 1 if not cnt else dct[ch] + 1
			for key in dctB:
				if not dct.get(key) or dct[key] < dctB[key]:
					univ = False
					break
			if univ:
				res.append(word)
		return res


def createHist(word):
	hist = {}
	for c in word:
		if c in list(hist.keys()):
			hist[c] += 1
		else:
			hist[c] = 1
	return hist

def isSubset(word1, word2Hist):
	word1Hist = createHist(word1)
	for c in list(word2Hist.keys()):
		if c in list(word1Hist.keys()):
			word1Occur = word1Hist[c]
			word2Occur = word2Hist[c]
			if word2Occur > word1Occur:
				return False
		else:
			return False
	return True

def isUniversal(word, bHist):
	if isSubset(word, bHist) == False:
		return False
	return True

def createMaxHistogram(arr):
	hist = {}
	for word in arr:
		wordHist = createHist(word)
		for key in list(wordHist.keys()):
			if key in list(hist.keys()):
				hist[key] = max(hist[key], wordHist[key])
			else:
				hist[key] = wordHist[key]
	return hist

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		res = []
		bHist = createMaxHistogram(B)
		for word in A:
			if isUniversal(word, bHist):
				res.append(word)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		d = collections.defaultdict(int)
		for b in B:
			b = collections.Counter(b)
			for x in b:
				if b[x] > d[x]:
					d[x] += b[x] - d[x]
		uni = []
		for a in A:
			c = collections.Counter(a)
			for (i, n) in list(d.items()):
				if i not in c or c[i] < n:
					break
			else:
				uni.append(a)
		return uni


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:

		def is_subset(b_dict, a_dict):
			for k in b_dict:
				if k not in a_dict or a_dict[k] < b_dict[k]:
					return False
			return True

		def get_dict(b):
			counts = {}
			for ch in b:
				counts[ch] = counts.get(ch, 0) + 1
			return counts
		b_dicts = [get_dict(b) for b in B]
		max_b_dict = {}
		for b_dict in b_dicts:
			for key in b_dict:
				max_b_dict[key] = max(max_b_dict.get(key, 0), b_dict[key])
		out = []
		for a in A:
			a_dict = get_dict(a)
			if is_subset(max_b_dict, a_dict):
				out.append(a)
		return out


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		d = defaultdict(lambda : 0)
		for b in B:
			temp = defaultdict(lambda : 0)
			for i in b:
				temp[i] += 1
			for (k, v) in list(temp.items()):
				d[k] = max(v, d[k])
		output = []
		for a in A:
			temp = defaultdict(lambda : 0)
			for i in a:
				temp[i] += 1
			add = True
			for (k, v) in list(d.items()):
				if k not in temp or v > temp[k]:
					add = False
					break
			if add:
				output.append(a)
		return output


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		dict2 = {}
		for i2 in B:
			dict3 = {}
			for l in i2:
				if l in dict3.keys():
					dict3[l] += 1
				else:
					dict3[l] = 1
				if l not in dict2.keys():
					dict2[l] = 0
				if dict3[l] > dict2[l]:
					dict2[l] = dict3[l]
		result = []
		for i in A:
			dict1 = {}
			is_subset = True
			for l1 in i:
				if l1 in dict1.keys():
					dict1[l1] += 1
				else:
					dict1[l1] = 1
			for key in dict2.keys():
				if key in dict1.keys():
					if dict1[key] < dict2[key]:
						is_subset = False
				else:
					is_subset = False
			if is_subset:
				result.append(i)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		bLets = collections.Counter()
		for w in B:
			for (l, cnt) in collections.Counter(w).items():
				if cnt > bLets[l]:
					bLets[l] = cnt
		bLets = bLets.most_common()
		result = []
		for w in A:
			aLets = collections.Counter(w)
			for (l, cnt) in bLets:
				if cnt > aLets[l]:
					break
			else:
				result.append(w)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		final = []
		D = {}
		for i in B:
			b_counter = collections.Counter(i)
			for j in b_counter:
				D[j] = max(b_counter[j], D.get(j, 0))
		for i in A:
			flag = True
			w = collections.Counter(i)
			for d in D:
				if w.get(d) and w[d] >= D[d]:
					pass
				else:
					flag = False
					break
			if flag:
				final.append(i)
		return final


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		ret = []
		bdict = dict()
		for word in B:
			temp = collections.Counter(word)
			for (let, val) in temp.items():
				if let not in bdict:
					bdict[let] = val
				else:
					bdict[let] = max(bdict[let], val)
		for item in A:
			tempdict = collections.Counter(item)
			failed = False
			for (let, val) in bdict.items():
				if let not in tempdict:
					failed = True
					break
				elif tempdict[let] < val:
					failed = True
					break
			if not failed:
				ret.append(item)
		return ret


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		B_dict = collections.defaultdict(int)
		for elem in B:
			elem_dict = collections.Counter(elem)
			for item in elem_dict:
				B_dict[item] = max(B_dict[item], elem_dict[item])
		output = []
		for elem in A:
			found = True
			elem_dict = collections.Counter(elem)
			for item in B_dict:
				if item not in elem_dict or elem_dict[item] < B_dict[item]:
					found = False
					break
			if found:
				output.append(elem)
		return output


from collections import Counter

class Solution:

	def parse_word(self, word):
		return Counter(word)

	def update_counter(self, orig, new):
		for c in new:
			orig[c] = max(new[c], orig[c])

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		min_universal = Counter()
		for b in B:
			bc = Counter(b)
			self.update_counter(min_universal, bc)
		universals = []
		for a in A:
			ac = Counter(a)
			is_universal = True
			for c in min_universal:
				if ac[c] < min_universal[c]:
					is_universal = False
					break
			if is_universal:
				universals.append(a)
		return universals


import collections

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		res = []
		bcount = collections.defaultdict(int)
		for s in B:
			counter = collections.Counter(s)
			for c in list(counter.keys()):
				if bcount[c] < counter[c]:
					bcount[c] = counter[c]
		for s in A:
			counter = collections.Counter(s)
			flag = True
			for c in list(bcount.keys()):
				if not counter[c] >= bcount[c]:
					flag = False
					break
			if flag:
				res.append(s)
		return res


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		bcounter = Counter()
		for b in B:
			bbc = Counter(b)
			for c in bbc:
				if c not in bcounter or bbc[c] > bcounter[c]:
					bcounter[c] = bbc[c]
		ans = []
		for a in A:
			aac = Counter(a)
			uni = True
			for c in bcounter:
				if c not in aac or aac[c] < bcounter[c]:
					uni = False
					break
			if uni:
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		dictionary = dict()
		for i in range(len(B)):
			prev_dict = dict(dictionary)
			for j in range(len(B[i])):
				char = B[i][j]
				if char in dictionary:
					dictionary[char] += 1
				else:
					dictionary[char] = 1
				if char not in prev_dict:
					prev_dict[char] = 0
			for (key, value) in list(prev_dict.items()):
				if dictionary[key] - prev_dict[key] > prev_dict[key]:
					dictionary[key] -= prev_dict[key]
				else:
					dictionary[key] = prev_dict[key]
		answer = []
		for i in range(len(A)):
			current_dict = dict(dictionary)
			for j in range(len(A[i])):
				char_a = A[i][j]
				if char_a in current_dict:
					current_dict[char_a] -= 1
			include_word = True
			for (key, value) in list(current_dict.items()):
				if value > 0:
					include_word = False
			if include_word:
				answer.append(A[i])
		return answer


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		total = Counter()
		for word in B:
			counts = Counter(word)
			for (ch, count) in list(counts.items()):
				total[ch] = max(total[ch], count)
		result = []
		for word in A:
			counts = Counter(word)
			is_universal = True
			for (ch, count) in list(total.items()):
				if counts[ch] < count:
					is_universal = False
					break
			if is_universal:
				result.append(word)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		if not B:
			return A
		mapB = collections.defaultdict(int)
		for b in B:
			counter = collections.Counter(b)
			for k in counter:
				mapB[k] = max(counter[k], mapB[k])
		res = []
		for a in A:
			countA = collections.Counter(a)
			if all((countA[ch] >= mapB[ch] for ch in mapB)):
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		um = {}
		result = []
		for b in B:
			for letter in b:
				if letter not in um:
					um[letter] = b.count(letter)
				elif b.count(letter) > um[letter]:
					um[letter] = b.count(letter)
		for a in A:
			boola = True
			for (i, n) in um.items():
				if i not in a or a.count(i) < n:
					boola = False
					break
			if boola:
				result.append(a)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		(A_cnt, B_cnt) = ([], collections.defaultdict(int))
		for a in A:
			A_cnt += [collections.Counter(a)]
		for b in B:
			b_cnt = collections.Counter(b)
			for key in b_cnt:
				B_cnt[key] = max(B_cnt[key], b_cnt[key])
		ret = []
		for (i, a) in enumerate(A_cnt):
			valid = True
			for key in B_cnt:
				if a[key] < B_cnt[key]:
					valid = False
					break
			if valid:
				ret += [A[i]]
		return ret


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		maxCountB = {}
		for w in B:
			c = Counter(w)
			for (k, cnt) in list(c.items()):
				maxCountB[k] = max(maxCountB.get(k, 0), cnt)
		res = []
		for w in A:
			c = Counter(w)
			isUniversal = True
			for (k, cnt) in list(maxCountB.items()):
				if k not in c or cnt > c[k]:
					isUniversal = False
					break
			if isUniversal:
				res.append(w)
		return res


from collections import defaultdict, Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		rd = defaultdict(int)
		for c in map(Counter, B):
			for i in c:
				rd[i] = max(rd[i], c[i])
		cts = {i: Counter(i) for i in A}
		for i in rd:
			rdi = rd[i]
			keep = {}
			for c in cts:
				if i in cts[c] and cts[c][i] >= rdi:
					keep[c] = cts[c]
			cts = keep
		return cts


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		counts_A = [Counter(a) for a in A]
		word_B = Counter()
		for b in B:
			for (k, v) in Counter(b).items():
				if k not in word_B or word_B[k] < v:
					word_B[k] = v
		ans = []
		for (i, a) in enumerate(counts_A):
			ind = 1
			for letter in word_B.keys():
				if letter not in a or a[letter] < word_B[letter]:
					ind = 0
					break
			if ind:
				ans.append(A[i])
		return ans


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		cnt = Counter()
		for word in B:
			wordcnt = Counter(word)
			for c in wordcnt:
				if cnt[c] < wordcnt[c]:
					cnt[c] = wordcnt[c]
		ans = []
		for word in A:
			wordcnt = Counter(word)
			if all((wordcnt[c] >= cnt[c] for c in cnt)):
				ans.append(word)
		return ans


from collections import defaultdict, Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		rd = defaultdict(int)
		for c in map(Counter, B):
			for i in c:
				rd[i] = max(rd[i], c[i])
		cts = {i: Counter(i) for i in A}
		for i in rd:
			rdi = rd[i]
			rm = set()
			for c in cts:
				if i not in cts[c] or cts[c][i] < rdi:
					rm.add(c)
			for r in rm:
				cts.pop(r)
		return cts


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		ret = []
		bdict = dict()
		for word in B:
			temp = collections.Counter(word)
			for (let, val) in temp.items():
				if let not in bdict:
					bdict[let] = val
				else:
					bdict[let] = max(bdict[let], val)
		i = 0
		while i < len(A):
			tempdict = collections.Counter(A[i])
			failed = False
			for (let, val) in bdict.items():
				if let not in tempdict:
					failed = True
					break
				elif tempdict[let] < val:
					failed = True
					break
			if failed:
				del A[i]
			else:
				i = i + 1
		return A


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		A = [(Counter(a), a) for a in A]
		B = [Counter(b) for b in B]
		req = {}
		for cntr in B:
			for (k, v) in list(cntr.items()):
				req[k] = max(req.get(k, 0), v)
		sol = [a for (cntr, a) in A if all((cntr.get(k, 0) >= v for (k, v) in list(req.items())))]
		return sol


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		Acount = {word: collections.Counter(word) for word in A}
		Bcount = defaultdict(int)
		for b in B:
			b = collections.Counter(b)
			for (k, v) in b.items():
				Bcount[k] = max(Bcount[k], v)
		res = []
		for word in A:
			wCount = Acount[word]
			isWord = True
			for (k, v) in Bcount.items():
				if k in wCount and wCount[k] >= v:
					continue
				else:
					isWord = False
					break
			if isWord:
				res.append(word)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		common_counter = defaultdict(int)
		for b_str in B:
			b_cnt = Counter(b_str)
			for (b_let, b_let_cnt) in b_cnt.items():
				common_counter[b_let] = max(common_counter[b_let], b_let_cnt)
		result = []
		for a_str in A:
			a_cnt = Counter(a_str)
			if all((a_cnt.get(c_let, 0) >= c_let_cnt for (c_let, c_let_cnt) in common_counter.items())):
				result.append(a_str)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		d = {}
		for i in B:
			temp = Counter(i)
			for j in temp:
				d[j] = max(d.get(j, 0), temp[j])
		ans = []
		for i in A:
			temp = Counter(i)
			flag = True
			for j in d:
				if temp.get(j) and temp[j] >= d[j]:
					pass
				else:
					flag = False
					break
			if flag:
				ans.append(i)
		return ans


import collections

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		B_count = collections.Counter()
		for ele in B:
			B_count |= collections.Counter(ele)
		res = []
		for ele in A:
			ele_count = collections.Counter(ele)
			for (letter, count) in list(B_count.items()):
				if ele_count[letter] < count:
					break
			else:
				res.append(ele)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b_chars = defaultdict(int)
		for b in B:
			chars = Counter(b)
			for c in b:
				b_chars[c] = max(b_chars[c], chars[c])
		output = []
		for a in A:
			a_chars = Counter(a)
			if all((a_chars[c] >= b_chars[c] for c in b_chars)):
				output.append(a)
		return output


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		book = collections.defaultdict(int)
		for b in B:
			book2 = Counter(b)
			for bb in book2:
				book[bb] = max(book[bb], book2[bb])
		res = []
		for a in A:
			aa = Counter(a)
			if all((k in aa and aa[k] >= book[k] for k in book)):
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		counter_b = Counter()
		for b in B:
			for (key, freq) in Counter(b).items():
				counter_b[key] = max(counter_b[key], freq)
		ans = []
		for a in A:
			counter_a = Counter(a)
			for (key, freq) in counter_b.items():
				if counter_a[key] < freq:
					break
			else:
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		(d, ret) = ({}, [])
		for word in B:
			b = Counter(word)
			for (key, val) in list(b.items()):
				if key not in d:
					d[key] = val
				else:
					d[key] = max(d[key], val)
		for cand in A:
			flag = True
			a = Counter(cand)
			for (key, val) in list(d.items()):
				if key not in a or val > a[key]:
					flag = False
			if flag:
				ret.append(cand)
		return ret


import collections as clc

class Solution:

	def subset(self, counter1: clc.Counter, counter2: clc.Counter) -> bool:
		return all((cnt1 <= counter2[char] for (char, cnt1) in counter1.items()))

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		max_b_counter = clc.Counter()
		for b in B:
			for (char, cnt) in clc.Counter(b).items():
				max_b_counter[char] = max(max_b_counter[char], cnt)
		ans = []
		for a in A:
			if self.subset(max_b_counter, clc.Counter(a)):
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		d = collections.Counter()
		for w in B:
			for (c, n) in collections.Counter(w).items():
				d[c] = max(n, d[c])
		res = []
		for w in A:
			t = collections.Counter(w)
			if all((t[x] >= d[x] for x in d)):
				res.append(w)
		return res


from collections import Counter

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		res = []
		counter_b = Counter()
		for b in B:
			tmp = Counter(b)
			for t in tmp:
				counter_b[t] = max(counter_b[t], tmp[t])
		for a in A:
			count = Counter(a)
			invalid = False
			for c in counter_b:
				if count[c] < counter_b[c]:
					invalid = True
			if not invalid:
				res.append(a)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		max_b_counter = defaultdict(int)
		for word in B:
			word_counter = Counter(word)
			for (char, counter) in list(word_counter.items()):
				max_b_counter[char] = max(max_b_counter[char], word_counter[char])
		result = []
		for word in A:
			word_counter = Counter(word)
			if all([max_b_counter[char] <= word_counter[char] for char in max_b_counter]):
				result.append(word)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		b = collections.Counter(B[0])
		f = collections.defaultdict(int)
		for x in B:
			p = Counter(x)
			for k in list(p.keys()):
				if k in b:
					b[k] = max(p[k], b[k])
				else:
					b[k] = p[k]
		res = []
		for word in A:
			word_counter = collections.Counter(word)
			add = True
			for i in b:
				if i not in word_counter or b[i] > word_counter[i]:
					add = False
			if add:
				res.append(word)
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		counter = Counter()
		for b in B:
			cb = Counter(b)
			for ch in cb:
				counter[ch] = max(counter[ch], cb[ch])
		ans = []
		for a in A:
			ca = Counter(a)
			if all((ca[ch] >= counter[ch] for ch in counter)):
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		a_counts = [Counter(a) for a in A]
		b_count = Counter()
		for b in B:
			for (l, c) in list(Counter(b).items()):
				b_count[l] = max(b_count[l], c)
		uni = []
		for (i, ac) in enumerate(a_counts):
			is_universal = True
			for (l, c) in list(b_count.items()):
				if ac[l] < c:
					is_universal = False
					break
			if is_universal:
				uni.append(A[i])
		return uni


import collections

class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		A = [(a, collections.Counter(a)) for a in A]
		newB = {}
		for b in B:
			for (x, c) in collections.Counter(b).items():
				newB[x] = c if x not in newB else max(newB[x], c)
		B = newB
		ans = []
		for (a, counts) in A:
			allMatch = True
			for (x, c) in B.items():
				if counts[x] < c:
					allMatch = False
					break
			if allMatch:
				ans.append(a)
		return ans


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		a_counter = [Counter(a) for a in A]
		b_counter = [Counter(b) for b in B]
		bc = {}
		for counter in b_counter:
			for (b, frequency) in counter.items():
				if b in bc:
					bc[b] = max(bc[b], frequency)
				else:
					bc[b] = frequency

		def is_bc_in_ac(ai, ac):
			if len(bc) > len(A[ai]):
				return False
			for (l, frequency) in bc.items():
				if ac[l] < frequency:
					return False
			return True
		res = []
		for (ai, ac) in enumerate(a_counter):
			if is_bc_in_ac(ai, ac):
				res.append(A[ai])
		return res


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		hashmap = defaultdict(int)
		for i in B:
			c = defaultdict(int)
			for p in i:
				c[p] += 1
			for n in c:
				hashmap[n] = max(hashmap[n], c[n])
		result = []
		for i in A:
			count = defaultdict(int)
			for c in i:
				count[c] += 1
			flag = True
			for node in hashmap:
				if node not in count or count[node] < hashmap[node]:
					flag = False
			if flag:
				result.append(i)
		return result


class Solution:

	def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
		max_counts = collections.defaultdict(int)
		for b in B:
			counts = collections.Counter(b)
			for (char, count) in list(counts.items()):
				max_counts[char] = max(max_counts[char], count)
		universals = []
		for a in A:
			counts = collections.Counter(a)
			for (char, max_count) in list(max_counts.items()):
				if counts[char] < max_count:
					break
			else:
				universals.append(a)
		return universals