JZ52 正则表达式匹配
正则表达式匹配
题目:请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。
首先题目要理解,通配符*是重复前面一个元素,而不是*前面所有的元素。而且通配符*号前面必须要有元素,就是说*出现的位置不可能在第一位。
f[i][j] = f[i][j - 2] || (s[i - 1] == p[j - 2] || '.' == p[j - 2]) && f[i - 1][j];
f[i][j - 2]表示前面的元素出现0次,后面表示出现次数大于等于1.
aabbb
aab.*
能够出现多次,说明s中减少一个(i -1)也能匹配,所以这个条件也必须满足。
s[i - 1] == p[j - 2]因为ij表示出现的元素个数,相当于下标从i - 1,j - 1.
表示p中倒数第二个元素要和s中倒数第一个元素相等。这样才能进行重复。
func match(s, p string) bool { sSize := len(s) pSize := len(p) dp := make([][]bool, sSize+1) for i := range dp { dp[i] = make([]bool, pSize+1) } /* dp[i][j] 代表了 s[:i] 能否与 p[:j] 匹配 */ dp[0][0] = true /** * 根据题目的设定, "" 可以与 "a*b*c*" 相匹配 * 所以,需要把相应的 dp 设置成 true */ for j := 1; j < pSize && dp[0][j-1]; j += 2 { if p[j] == '*' { dp[0][j+1] = true } } for i := 0; i < sSize; i++ { for j := 0; j < pSize; j++ { if p[j] == '.' || p[j] == s[i] { /* p[j] 与 s[i] 可以匹配上,所以,只要前面匹配,这里就能匹配上 */ dp[i+1][j+1] = dp[i][j] } else if p[j] == '*' { /* 此时,p[j] 的匹配情况与 p[j-1] 的内容相关。 */ if p[j-1] != s[i] && p[j-1] != '.' { /** * p[j] 无法与 s[i] 匹配上 * p[j-1:j+1] 只能被当做 "" */ dp[i+1][j+1] = dp[i+1][j-1] } else { /** * p[j] 与 s[i] 匹配上 * p[j-1;j+1] 作为 "x*", 可以有三种解释 */ dp[i+1][j+1] = dp[i+1][j-1] || /* "x*" 解释为 "" */ dp[i+1][j] || /* "x*" 解释为 "x" */ dp[i][j+1] /* "x*" 解释为 "xx..." */ } } } } return dp[sSize][pSize] }