力扣 剑指 Offer 19. 正则表达式匹配

在这里插入图片描述
困难题

思路:遍历正则表达式,查找正则表达式的前 i 项能匹配 字符串的前多少项(可能有很多种匹配方式),这样的话,对于每一个 i 我们都能得到一个列表,并且每一个 i 对应的列表是通过 i - 1 对应的列表得到的。递推到最后,如果列表中含有字符串的最后一项则返回true。总体是一个动态规划的思想。
4ms 24%

class Solution {
    public boolean isMatch(String s, String p) {
        if(p.length() == 0)
            return s.length() == 0 ? true : false;
        int index = 0;
        List<Integer> l = new ArrayList<>();
        l.add(0);
        while(index < p.length()){
            List<Integer> t = new ArrayList<>();
            if(p.charAt(index) == '.'){
                if(index + 1 < p.length() && p.charAt(index + 1) == '*'){
                    index ++;
                    for(Integer j:l)
                        for(int i = j; i <= s.length(); i++)
                            t.add(i);
                }
                else{
                    for(Integer i:l)
                        t.add(i + 1);
                }
            }else{
                if(index + 1 < p.length() && p.charAt(index + 1) == '*'){
                    index ++;
                    for(Integer i:l){
                        t.add(i);
                        int j = i;
                        while(j < s.length() && s.charAt(j) == p.charAt(index - 1)){
                            t.add(j + 1);
                            j++;
                        }
                    }
                }
                else {
                    int num = 0;
                    for(Integer i:l){
                        if(i < s.length() && s.charAt(i) == p.charAt(index)){
                            t.add(i + 1);
                        }
                        else
                            num ++;
                    }
                    if(num == l.size())
                        return false;
                }
            }
            index ++;
            Set<Integer> set = new HashSet<>(t);
            t = new ArrayList<>(set);
            l.clear();
            l.addAll(t);
        }
        if(l.contains(s.length()))
            return true;
        else
            return false;
    }
}

更好的动规思想:定义二维数组 dp[i][j] 代表正则表达式的前 i 项 是否能与字符串的前 j 项相匹配。因为是对于每一个 i 遍历 j,所以就是对于 字符串的前 i 项 查找正则表达式的前 j 项能否匹配后再查找 i+1项,那么对于如果在 i + 1 时 第 j 项是 ’ * ',并且i + 1 与 j - 1项匹配,我们想要知道 ’ * '到底重复用了多少次,只需判断dp[i][j] 即可。还是看代码吧,

1ms 100%

class Solution {
    public boolean isMatch(String s, String p) {
        int m = s.length();
        int n = p.length();

        boolean[][] f = new boolean[m + 1][n + 1];
        // s 与 p 都为空时,为 true
        f[0][0] = true;
        for (int i = 0; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (p.charAt(j - 1) == '*') {
                    // 如果第 j 项为 *
                    f[i][j] = f[i][j - 2];
                    if (matches(s, p, i, j - 1)) {
                        // 若 s 的第 i 项,匹配 p 的 第 j-1 项
                        // 那么 f[i][j] = *一个都没有匹配(f[i][j - 2]),s递归往前匹配(f[i - 1][j])
                        f[i][j] = f[i][j] || f[i - 1][j];
                    }
                } else {
                    // 如果不为 *,直接看是否匹配就行
                    if (matches(s, p, i, j)) {
                        f[i][j] = f[i - 1][j - 1];
                    }
                }
            }
        }
        return f[m][n];
    }

    public boolean matches(String s, String p, int i, int j) {
        if (i == 0) {
            return false;
        }
        if (p.charAt(j - 1) == '.') {
            return true;
        }
        return s.charAt(i - 1) == p.charAt(j - 1);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eyvr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值