-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathshortest-matching-substring.py
105 lines (99 loc) · 3.04 KB
/
shortest-matching-substring.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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# 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