-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathregex_matching.go
78 lines (69 loc) · 1.7 KB
/
regex_matching.go
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
package problem0010
/*
Given an input string s and a pattern p, implement regular expression matching with support for '.' and '*' where:
'.' Matches any single character.
'*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
*/
const (
RegularCell = iota
EndCell
)
const (
RealRoute = iota
FakeRoute
)
func isMatch(s string, p string) bool {
return MakeRegex(p).MatchRegex(s)
}
type RegeCell struct {
Special int
Routes []Route
}
type Route struct {
Match byte
Type int
Dest *RegeCell
}
// MakeRegex makes the NFA from a pattern
func MakeRegex(pattern string) *RegeCell {
var cur *RegeCell = &RegeCell{Special: EndCell}
for i := len(pattern) - 1; i >= 0; i-- {
if pattern[i] == '*' {
// For a * we point the cell to itself
cur.Routes = append(cur.Routes, Route{pattern[i-1], RealRoute, cur})
cur = &RegeCell{Special: cur.Special, Routes: []Route{{'.', FakeRoute, cur}}}
i--
} else {
// For a regular character or wildcard we make a new cell
cur = &RegeCell{Routes: []Route{{pattern[i], RealRoute, cur}}}
}
}
return cur
}
func (rc *RegeCell) MatchRegex(str string) bool {
// Exiting if string is empty
if str == "" {
return rc.Special == EndCell
}
// Because * can make multiple routes,
// we need to check every one
for _, rt := range rc.Routes {
if rt.Type == RealRoute {
if rt.Match == str[0] || rt.Match == '.' {
if rt.Dest.MatchRegex(str[1:]) {
return true
}
}
} else {
//Fake Routes are like regular routes
//but they don't decrement the string
if rt.Match == str[0] || rt.Match == '.' {
if rt.Dest.MatchRegex(str) {
return true
}
}
}
}
return false
}