20240226

正则表达式匹配(hot100 hard)

太难想到了,暴力过了2/3左右,粘贴leetcode解析便于复习

思路:动态规划

定义 dp[i][j]表示 s 的前 i 个字符和 p的前 j 个字符能否匹配,分以下几种情况讨论:

1、p[j] 是一个小写字母a-z,则 s[i]必须也为同样的小写字母方能完成匹配

2、p[j] 为'.',则p[i]与s[j]一定能匹配上,因为p[j]可以与任意字母相等,即dp[i][j] = dp[i - 1][j - 1]

3、p[j] 为'*',p[j]的前一个字符 p[j−1]匹配任意次(包括 0 次,p[j - 1]为'.'视作匹配),此时从0开始举几个例子:

(1)匹配0次,则p[j - 1] != s[i],则p字符串的0到j - 1位与s字符串的0到i位一定不匹配,此时应考虑p字符串的0到j - 2位

位与s字符串的0到i位的匹配性,即dp[i][j] = dp[i][j - 2];

(2)匹配1次,则p[j - 1] = s[i],p字符串第j - 1到j位一定与s字符串的第i位长度为1的子串匹配(例如a与a*匹配,a*转化为a),那么需判断p字符串第0到j - 2位一定与p字符串第0到i - 1位的匹配性,即dp[i][j] = dp[i - 1][j - 2];

(3)匹配2次,则p[j - 1] = s[i] = s[i - 1],p字符串第j - 1到j位一定与s字符串第i - 1到i位匹配(例如aa与a*匹配,a*转化为aa),那么需判断p字符串第0到j - 2位一定与p字符串第0到i - 2位的匹配性,即dp[i][j] = dp[i - 2][j - 2];

(4)以此类推,匹配k次,即p[j - 1] = s[i] = s[i - 1] = ... = s[i - k + 1],则p字符串第j - k + 1到j位一定与s字符串第i - 1到i位匹配(例如aa...a(共k个a)与a*匹配,a*转化为aa...a(共k个a)),那么需判断p字符串第0到j - 2位一定与p字符串第0到i - k位的匹配性,即dp[i][j] = dp[i - k][j - 2]。

图示如下:

优化方法如下:

因此此时dp[i][j] = dp[i][j - 2] || (dp[i - 1][j] && (s[i] = p[j - 1] || p[j - 1] = '.'))

初始条件:

AC代码:

    public boolean isMatch(String s, String p) {
        int m = s.length();
        int n = p.length();
        boolean[][] dp = new boolean[m + 1][n + 1];
        dp[0][0] = true;
        for(int i = 1; i <= n; i++){
            if(p.charAt(i - 1) == '*'){
                dp[0][i] = dp[0][i - 2];
            }
        }
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                if(s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.'){
                    dp[i][j] = dp[i - 1][j - 1];
                }else if(p.charAt(j - 1) == '*'){
                    dp[i][j] = dp[i][j - 2] | (dp[i - 1][j] && (s.charAt(i - 1) == p.charAt(j - 2) | p.charAt(j - 2) == '.'));
                }
            }
        }
        return dp[m][n];
    }

全部评论

相关推荐

05-20 13:59
门头沟学院 Java
米黑子米黑子:你这个成绩不争取下保研?
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务