class Solution {
public boolean isMatch(String s, String p) {
int n = s.length();
int m = p.length();
boolean[][] dp = new boolean[n+1][m+1];
dp[0][0] = true;//空串和空正则匹配
for(int i = 1;i <= n;i++){
dp[i][0] = false;//非空串和正则一定不匹配
}
//非空正则和(空串和非空串匹配)
for(int i = 0;i <= n;i++){
for(int j = 1;j <= m;j++){
if(m==1){
dp[i][j] = false;//特殊处理,如果第一个字符为空,正则第一个为*,必失败
}else if(i==0){
dp[i][j] = false;//特殊处理
}
if(p.charAt(j-1)=='*'){
dp[i][j] = dp[i][j-2];
if(i!=0 && ((p.charAt(j-2)==s.charAt(i-1))||p.charAt(j-2)=='.')){
dp[i][j] = dp[i][j] || dp[i-1][j];//如果正则最后一个字符匹配成功,就将字串减
}else{
dp[i][j] = dp[i][j-2];//如果正则最后一个字符匹配失败,正则减2
}
}else if(i!=0 && p.charAt(j-1)=='.'){
dp[i][j] = dp[i-1][j-1];//如果是.一定匹配成功,同时前退1
}else if(i!=0 && p.charAt(j-1)==s.charAt(i-1)){
dp[i][j] = dp[i-1][j-1];//如果是匹配的字符就同时前退1
}
}
}
return dp[n][m];
}
}
需要注意的点,遇到*号开始倒推时,应该先假设没有匹配成功,再逐步退回字符来判断是否成功。最重要的是先假设没有匹配成功,因为如果先退回字符有可能退的超过指定字符,所以先假设没有匹配成功,这样就可以获取没有超退回字符状态下能否匹配成功,再将没有回退的装态和超出回退的状态取余,就可以保证不会超出回退。