github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/algorithm/datastructures/dp/regex_pattern_test.go (about) 1 package dp 2 3 import ( 4 "github.com/bmizerany/assert" 5 "testing" 6 ) 7 8 // 正则匹配 9 type Pattern struct { 10 matched bool // 是否匹配的全局值 11 pattern []rune // 正则串 12 } 13 14 func NewPattern(expr string) *Pattern { 15 return &Pattern{pattern: []rune(expr)} 16 } 17 18 func (p *Pattern) Match(text string) bool { // 文本串及长度 19 p.matched = false 20 p.rmatch(0, 0, []rune(text)) 21 //p.rmatchDp([]rune(text)) 22 return p.matched 23 } 24 25 /* 26 只有 * 和 ? 两种通配符 27 * 表示任意多(>=0)个字符 28 ? 表示0个或1任意字符 29 30 使用回溯的方式实现 31 32 ti 表示待匹配字符的指针 33 pj 表示正则表达式指针位置 34 */ 35 36 func (p *Pattern) rmatch(ti, pj int, text []rune) { 37 if p.matched { // 已经匹配 38 return 39 } 40 if pj == len(p.pattern) { // 正则串到结束 41 if ti == len(text) { 42 // 文本串也结束 找到匹配 43 p.matched = true 44 } 45 return 46 } 47 // -----递归出口分割线----- 48 switch { 49 case p.pattern[pj] == '*': // 匹配多个字符 50 for k := 0; k < len(text)-ti; k++ { 51 p.rmatch(ti+k, pj+1, text) 52 } 53 case p.pattern[pj] == '?': //匹配0个或1个 54 p.rmatch(ti, pj+1, text) 55 p.rmatch(ti+1, pj+1, text) 56 case ti < len(text) && p.pattern[pj] == text[ti]: // 纯字符匹配才能继续,也属于剪枝操作 57 p.rmatch(ti+1, pj+1, text) 58 } 59 } 60 61 // 使用动态规划的方式怎么写? 62 // 状态 dp [ti][pj]bool 表示ti,pi的位置是否匹配 63 func (p *Pattern) rmatchDp(text []rune) { 64 tn := len(text) 65 pn := len(p.pattern) 66 67 dp := make([][]bool, tn) 68 for i := range dp { 69 dp[i] = make([]bool, pn) 70 } 71 // init first line 72 switch p.pattern[0] { 73 case '*': 74 for i := 0; i < pn; i++ { 75 dp[0][i] = true 76 } 77 case '?': 78 dp[0][0] = true 79 case text[0]: 80 dp[0][0] = true 81 } 82 for ti := 1; ti < tn; ti++ { 83 for pi := 0; pi < pn; pi++ { 84 switch p.pattern[pi] { 85 case '*': 86 87 case '?': 88 case text[ti]: 89 } 90 } 91 } 92 93 p.matched = dp[tn-1][pn-1] 94 } 95 96 func TestMatch(t *testing.T) { 97 pattern := NewPattern("?c*html?") 98 assert.Equal(t, pattern.Match("chtml"), true) 99 assert.Equal(t, pattern.Match("cxxxxhtml"), true) 100 assert.Equal(t, pattern.Match("xxxxhtm"), false) 101 102 }