2
\$\begingroup\$

I'm trying to solve Wildcard Matching on LeetCode. I found a great solution using the Finite-state machine. The author builds an FSM and searches with BFS.

I rewrite the solution with the same idea (FSM) but use depth-first search (DFS):

class Solution:
 
 def isMatch(self, s: str, p: str) -> bool:
 # build the fsm
 fsm = {}
 state = 0
 for i in range(len(p)):
 if p[i] == "*":
 # connect to state itself
 fsm[state, p[i]] = state
 else:
 fsm[state, p[i]] = state + 1
 state += 1
 
 self.accept = state
 
 self.fsm = fsm
 return self.dfs(s, idx=0, state=0)
 
 
 def dfs(self, s: str, idx: int, state: int) -> bool:
 """deep first search through the finite state machine"""
 if idx == len(s):
 # processing string finished
 if state == self.accept:
 return True
 else:
 return False
 
 for value in [s[idx], "*", "?"]:
 if (state, value) not in self.fsm:
 # invaild state
 continue
 
 next_state = self.fsm[state, value]
 if self.dfs(s, idx + 1, next_state):
 return True
 
 return False

Since we need to iterate the whole string s, I think the time complexity of DFS and BFS are the same. However, I had the Time Limit Exceeded on the testing case:

"babbbbaabababaabbababaababaabbaabababbaaababbababaaaaaabbabaaaabababbabbababbbaaaababbbabbbbbbbbbbaabbb"
"b**bb**a**bba*b**a*bbb**aba***babbb*aa****aabb*bbb***a"
  1. Are the time complexity of DFS and BFS the same?
  2. Is there something wrong with my code?
toolic
14.4k5 gold badges29 silver badges201 bronze badges
asked Feb 23, 2020 at 11:19
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Documentation

It is great that you used type hints for the functions.

The PEP 8 style guide recommends adding docstrings for functions. I realize the code is submitted to the LeetCode site as a programming challenge, but for general code review, it would be good to add a docstring summarizing the purpose of the isMatch function. A description of the state machine would also be helpful.

The dfs function docstring is good:

"""deep first search through the finite state machine"""

but, it would be better to use the common name for the algorithm:

"""Depth-first search through the finite state machine"""

It would also be helpful to mention that the function is recursive.

Naming

PEP-8 recommends snake_case for function and variable names.

isMatch would be is_match (outside of LeetCode restrictions).

dfs could be depth_first_search.

s and p are a bit terse in this context. input_string and pattern would be better.

TLE

  1. Is there something wrong with my code?

Since the code does not hit the time goal, this is likely not the best approach. The link you posted for the FSM solution has a long discussion; perhaps there are some clues buried in there.

answered Mar 3 at 12:57
\$\endgroup\$
1
\$\begingroup\$

time complexity

I had the Time Limit Exceeded on the testing case: ...

"b**bb**a**bba*b**a*bbb**aba***babbb*aa****aabb*bbb***a"

(Using more standard regex notation from outside the problem statement, we might phrase that as "^b.*.*bb.*.*a ..." and so on.)

You seem to be touching on some classic "why does this egrep take forever?" gotchas. It is easy enough to write a short regex which hides some ugly deeply nested loops.

I won't comment on your dfs(). I will observe that there's an opportunity to simplify the input you're sending it. There's no difference between the following patterns:

  • a*b
  • a**b
  • a***b
  • a****b

You can simplify all of them down to "a*b" before invoking dfs().

answered Mar 3 at 19:22
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.