[The sword refers to the offer brushing the question] 30. Regular expression matching (dynamic programming)

Category: Dynamic Programming

State representation and state transition equations are difficult to think about. Yan-style DP

State representation: f[i][j] means p starts from j to the end, whether it can match s from the start to the end of i
State transition:

如果p[j+1]不是通配符'*',则f[i][j]是真,当且仅当s[i]可以和p[j]匹配,且f[i+1][j+1]是真;
  如果p[j+1]是通配符'*',则下面的情况只要有一种满足,f[i][j]就是真;
	1.  f[i][j+2]是真;
	2.  s[i]可以和p[j]匹配,且f[i+1][j]是真;

The state transition in the first case is easy to understand, but what about the state transition in the second case?
The most intuitive way to transfer is as follows: enumerate how many p[j] the wildcard '*' can match, as long as there is one case that can be matched, then f[i][j] is true; in
this way, we find that f [i][j] In addition to enumerating 0 p[j], the rest of the enumeration operations are included in f[i+1][j],
so we only need to judge f[i+1][ j] is true, and whether s[i] can match p[j].

topic

Please implement a function to match regular expressions including '.' and '*'.

The character '.' in the pattern means any character, and '*' means that the character preceding it can appear any number of times (including 0).

In this question, match means that all characters of the string match the entire pattern.

For example, the string "aaa" matches the patterns "aa" and "ab ac a", but neither "aa.a" nor "ab*a".
Sample

enter:

s=“aa”
p=“a*”

output: true

C++ code

class Solution {
    
    
public:
    vector<vector<int>>f;
    int n, m;
    bool isMatch(string s, string p) {
    
    
        n = s.size();
        m = p.size();
        f = vector<vector<int>>(n + 1, vector<int>(m + 1, -1));
        return dp(0, 0, s, p);
    }

    bool dp(int x, int y, string &s, string &p)
    {
    
    
        if (f[x][y] != -1) return f[x][y];
        if (y == m)
            return f[x][y] = x == n;
        bool first_match = x < n && (s[x] == p[y] || p[y] == '.');
        bool ans;
        if (y + 1 < m && p[y + 1] == '*')
        {
    
    
            ans = dp(x, y + 2, s, p) || first_match && dp(x + 1, y, s, p);
        }
        else
            ans = first_match && dp(x + 1, y + 1, s, p);
        return f[x][y] = ans;
    }
};

java code


/*
可以用二维动态规划来做

s为字符串,p为模式

状态表示:f[i][j] 表示s[i, ...] 和 p[j, ...]相匹配

状态转换:
1. p[j]是正常字符, f[i][j] = s[i] == p[j] && f[i+1][j+1];
2. p[j]是‘.’,f[i][j] = f[i+1][j+1];
3. p[j+1]是‘*’,f[i][j] = f[i][j+2] || f[i+1][j]
*/

class Solution {
    
    
    
    private int n, m; 
    int f[][];
    public boolean isMatch(String s, String p) {
    
    
        n = s.length();
        m = p.length();
        
        f = new int[n+1][m+1];
        // 初始化f
        for (int i = 0; i < (n + 1); i++) {
    
    
            for (int j = 0; j < (m + 1); j++)
                f[i][j] = -1;
        }
        return dp(0, 0, s, p) > 0 ? true : false;
    }
    
    public int dp(int x, int y, String s, String p) {
    
    
        if (f[x][y] != -1) return f[x][y];
        if (y == m) {
    
    
            int t = (x == n ? 1 : 0);
            f[x][y] = t;
            return f[x][y];
        }
        
        boolean first_match = false;
        if (x < n && (s.charAt(x) == p.charAt(y) || p.charAt(y) == '.'))
            first_match = true;
        
        boolean ans;
        if (y + 1 < m && p.charAt(y+1) == '*') {
    
    
            ans = (dp(x, y + 2, s, p) > 0) || first_match && (dp(x + 1, y, s, p) > 0);
        }
        else
            ans = first_match && (dp(x + 1, y + 1, s, p) > 0);
        f[x][y] = (ans ? 1 : 0);
        return f[x][y];
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326100235&siteId=291194637