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]
}

 

posted @ 2021-04-10 21:48  zqlucky  阅读(99)  评论(0编辑  收藏  举报