Given a text and a pattern, test if pattern matches text. Both text and pattern consist of only lowercase alphabets while pattern also consists special characters of "." and "*". "." matches any single character and "*" matches zero or more of the preceding character.
This algorithm uses memoization to improve performance. It's same as the recursive version of Regular expression wildcard pattern matching, but with a special 'cache' to store results. The 'cache key' is crucial. It's how we identify and store past results. Sometimes we need one key, sometimes multiple keys. We add code to:
cache = {}
def match(t, p):
if t not in cache:
cache[t] = {}
if p not in cache[t]:
cache[t][p] = False
if len(p) == 0:
cache[t][p] = len(t) == 0
elif len(t) == 0:
cache[t][p] = (p[-1] == '*' and len(p) >= 2) and match(t, p[0:-2])
elif t[-1] == p[-1] or p[-1] == '.':
cache[t][p] = match(t[0:-1], p[0:-1])
elif p[-1] == "*" and len(p) > 1:
zero = match(t, p[0:-2])
more = (p[-2] == t[-1] or p[-2] == '.') and match(t[0:-1], p)
cache[t][p] = zero or more
return cache[t][p]
text = "helloworld"
pattern = "hel*oworl."
print(match(text, pattern))
const cache = {}
function match(t, p) {
if (cache[t] === undefined) {
cache[t] = {}
}
if (cache[t][p] === undefined) {
cache[t][p] = false
if (p.length === 0) {
cache[t][p] = t.length === 0;
} else if (t.length === 0) {
cache[t][p] = (p.length >= 2 && p.at(-1) === '*') && match(t, p.slice(0, -2));
} else if (t.at(-1) === p.at(-1) || p.at(-1) === '.') {
cache[t][p] = match(t.slice(0, -1), p.slice(0, -1));
} else if (p.at(-1) === "*" && p.length > 1) {
let zero = match(t, p.slice(0, -2));
let more = (p.at(-2) == t.at(-1) || p.at(-2) === '.') && match(t.slice(0, -1), p);
cache[t][p] = zero || more;
}
}
return cache[t][p];
}
const text = "helloworld"
const pattern = "hel*oworl."
console.log(match(text, pattern));