题目链接: leetcode.cn/problems/re… 题目描述 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
- '.' 匹配任意单个字符
- '*' 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
这题是动态规划的经典题目,我们定义一个二维的数组dp。 dp[i][j]表示,s的[0,i-1]和p的[0,j-1]是否匹配。
状态转移
- 当s[i-1]=p[j-1]或p[j-1] = '.' 时,dp[i][j] = dp[i-1][j-1];
- 当p[j-1] = '*'时
- 当s[i-1]=p[j-2]或p[j-2]='.',说明*前面的字符可以和s[i-1]匹配,就是p[j-1]重复几次的问题。如果重复0次则dp[i][j] = dp[i][j-2];重复一次则dp[i][j] = dp[i-1][j-2];重复多次则dp[i][j] = dp[i-1][j]。
- 当s[i-1]!=p[j-2]时,则p[j-2]重复0次,dp[i][j] = dp[i][j-2]; 代码
bool isMatch(string s, string p) {
// 如果s不为空,p为空,直接返回false
if(s.size() && p.empty()){
return false;
}
// 两个都为空返回true
if(s.empty() && p.empty()){
return true;
}
int sLen = s.size();
int pLen = p.size();
bool dp[sLen+1][pLen+1];
memset(dp, false, (sLen+1)*(pLen+1));
dp[0][0] = true;
// 初始化
for(int j=1;j<=pLen;j++){
if(p[j-1] == '*'){
dp[0][j] = dp[0][j-2];
}
}
for(int i=1;i<=sLen;i++){
for(int j=1;j<=pLen;j++){
// 当s[i-1]=p[j-1]或p[j-1] = '.' 时,dp[i][j] = dp[i-1][j-1];
if(s[i-1] == p[j-1] || p[j-1] == '.'){
dp[i][j] = dp[i-1][j-1];
}else if(p[j-1] == '*'){
// 当s[i-1]=p[j-2]或p[j-2]='.',说明*前面的字符可以和s[i-1]匹配,就是p[j-1]重复几次的问题。如果重复0次则dp[i][j] = dp[i][j-2];重复一次则dp[i][j] = dp[i-1][j-2];重复多次则dp[i][j] = dp[i-1][j],三者只要有一个为true,则dp[i][j]就为true。
if(p[j-2] == s[i-1] || p[j-2] == '.'){
dp[i][j] = dp[i][j-2] || dp[i-1][j-2] || dp[i-1][j];
}else {
// 当s[i-1]!=p[j-2]时,dp\[i][j] = dp\[i][j-2];
dp[i][j] = dp[i][j-2];
}
}
}
}
return dp[sLen][pLen];
}