3455. Shortest Matching Substring
Read the full problem statement on LeetCode.
Difficulty: hard Acceptance: 22% Topics: Two Pointers, String, Binary Search, String Matching
View full problem on LeetCode Reading material
Reference solution (spoiler · python)
# Time: O(n + m)
# Space: O(n + m)
# kmp, two pointers (three pointers)
class Solution(object):
def shortestMatchingSubstring(self, s, p):
"""
:type s: str
:type p: str
:rtype: int
"""
INF = float("inf")
def getPrefix(pattern):
prefix = [-1]*len(pattern)
j = -1
for i in xrange(1, len(pattern)):
while j+1 > 0 and pattern[j+1] != pattern[i]:
j = prefix[j]
if pattern[j+1] == pattern[i]:
j += 1
prefix[i] = j
return prefix
def KMP(text, pattern):
if not pattern:
for i in xrange(len(text)+1):
yield i
return
prefix = getPrefix(pattern)
j = -1
for i in xrange(len(text)):
while j+1 > 0 and pattern[j+1] != text[i]:
j = prefix[j]
if pattern[j+1] == text[i]:
j += 1
if j+1 == len(pattern):
yield i-j
j = prefix[j]
a, b, c = p.split('*')
n = len(s)
la, lb, lc = len(a), len(b), len(c)
result = INF
j = k = 0
jt = KMP(s, b)
kt = KMP(s, c)
for i in KMP(s, a):
while j != -1 and j < i+la:
j = next(jt, -1)
if j == -1:
break
while k != -1 and k < j+lb:
k = next(kt, -1)
if k == -1:
break
result = min(result, (k+lc)-i)
return result if result != INF else -1
# Time: O(n + m)
# Space: O(n + m)
# kmp, two pointers (three pointers)
class Solution2(object):
def shortestMatchingSubstring(self, s, p):
"""
:type s: str
:type p: str
:rtype: int
"""
INF = float("inf")
def getPrefix(pattern):
prefix = [-1]*len(pattern)
j = -1
for i in xrange(1, len(pattern)):
while j+1 > 0 and pattern[j+1] != pattern[i]:
j = prefix[j]
if pattern[j+1] == pattern[i]:
j += 1
prefix[i] = j
return prefix
a, b, c = p.split('*')
n = len(s)
la, lb, lc = len(a), len(b), len(c)
prefix1 = getPrefix(a+'#'+s)
prefix2 = getPrefix(b+'#'+s)
prefix3 = getPrefix(c+'#'+s)
result = INF
i = j = k = 0
while i+lb+lc < n:
while i < n and prefix1[la+1+i]+1 != la:
i += 1
if i == n:
break
while j < n and not (j >= i+lb and prefix2[lb+1+j]+1 == lb):
j += 1
if j == n:
break
while k < n and not (k >= j+lc and prefix3[lc+1+k]+1 == lc):
k += 1
if k == n:
break
result = min(result, k-(i-la))
i += 1
return result if result != INF else -1
Solution from kamyu104/LeetCode-Solutions · MIT