-
Notifications
You must be signed in to change notification settings - Fork 17
/
number-of-valid-words-for-each-puzzle.py
50 lines (35 loc) · 1.47 KB
/
number-of-valid-words-for-each-puzzle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from typing import Dict, List
class Solution:
def findNumOfValidWords(self, words: List[str], puzzles: List[str]) -> List[int]:
# Can use Counter instead, but it is slower
# Build a number of times bitmap of a word met in a words array
# Bitmap represents letters exist in the word, it fits integer because
# alphabet size is 26
word_map: Dict[int, int] = {}
for word in words:
word_hash = 0
for letter in word:
word_hash |= 1 << (ord(letter) - ord("a"))
word_map.setdefault(word_hash, 0)
word_map[word_hash] += 1
def dfs(puzzle: str, pos: int, bitmap: int) -> int:
"""
Try to generate all variations of puzzle bitmap obtained by
preserving or removing arbitatrary characters
"""
if pos == len(puzzle):
return word_map.get(bitmap, 0)
letter_bitmap = 1 << (ord(puzzle[pos]) - ord("a"))
count = 0
# Skip
if pos != 0:
# Can't skip the first letter of the puzzle
count += dfs(puzzle, pos + 1, bitmap)
# Keep
count += dfs(puzzle, pos + 1, bitmap | letter_bitmap)
return count
count = [0] * len(puzzles)
for pos, puzzle in enumerate(puzzles):
# Calculate number of words for each puzzle
count[pos] = dfs(puzzle, 0, 0)
return count