剑指 Offer 19.正则表达式匹配
解法:动态规划
1、dp数组的含义:dp[i][j] : s的前i个字符和p的前j个字符是否可以匹配。
2、dp方程:从最后一个字符出发
- 当字符为正常字符且等于s[i-1]时,则dp[i][j]取决于dp[i-1][j-1]
- 当字符为‘.’时,dp[i][j]取决于dp[i-1][j-1]
- 当字符为‘*’时且q[j - 2] != s[i -1]而且q[j-2] != '.'时,去除掉最后两个字符,看倒数第三个字符,则dp[i][j]取决于dp[i][j-2];
- 当字符为‘*’时且q[j - 2] == s[i -1] 或者 q[j-2] == '.'时,可以选择匹配或不匹配,不匹配的话则去掉最后两个字符,看倒数第三个字符,则dp[i][j]取决于dp[i][j-2];选择匹配的话,则看s[i-2],dp[i][j]取决于dp[i-1][j]
3、初始化
class Solution {
public boolean isMatch(String s, String p) {
if(s == null && p == null) return true;
if(s != null && p == null) return false;
boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];//dp[i][j]代表前s前i个字符和p前j个字符匹配
dp[0][0] = true;
for(int j = 1; j <= p.length(); j++) { //初始化,判断p能不能化为null
if(j >= 2 && p.charAt(j - 1) == '*' && dp[0][j - 2] )
dp[0][j] = true;
}
for(int i = 1; i <= s.length(); i++)
for(int j = 1; j <= p.length(); j++) {
if(p.charAt(j - 1) == s.charAt(i - 1) || p.charAt(j - 1) == '.') {
dp[i][j] = dp[i - 1][j - 1]; //取决前i-1个字符与前j-1个字符是否相等
}
else if(p.charAt(j - 1) == '*' && j >= 2) {
if(p.charAt(j - 2) != s.charAt(i - 1) && p.charAt(j - 2) != '.') {
dp[i][j] = dp[i][j - 2]; //取决于前0~j-3个字符是否相等
}
else {
dp[i][j] = dp[i][j - 2] || dp[i - 1][j]; //可以选择匹配或不匹配
}
}
else dp[i][j] = false;
}
return dp[s.length()][p.length()];
}
}