题目:力扣https://leetcode-cn.com/problems/regular-expression-matching/
class Solution {
public boolean isMatch(String s, String p) {
//声明boolean数组dp
boolean[][] dp = new boolean[s.length()+1][p.length()+1];
dp[0][0] = true;
int num=0;
//初始化处理boolean数组
for(int i=1;i<s.length()+1;i++){
dp[i][0] = false;
}
for(int j=1;j<p.length()+1;j++){
if(p.charAt(j-1)=='*'){
dp[0][j] = dp[0][j-2];
}else if(p.charAt(j-1)=='.'){
dp[0][j] = dp[0][j-1];
num++;
if(j<p.length()&&p.charAt(j)=='*'){
num = 0;
}
}else{
dp[0][j] = false;
}
}
if(num>s.length()){
return false;
}
//根据规则判断T/F
for(int row=1;row<s.length()+1;row++){
for(int column=1;column<p.length()+1;column++){
if(s.charAt(row-1)==p.charAt(column-1) || p.charAt(column-1)=='.'){
dp[row][column] = dp[row-1][column-1];
}else if(p.charAt(column-1)=='*'){
if(dp[row][column-2]==true){
dp[row][column] = true;
}else if(s.charAt(row-1)==p.charAt(column-2)||p.charAt(column-2)=='.'){
dp[row][column] = dp[row-1][column];//
}
}else if(s.charAt(row-1)!=p.charAt(column-1)){
dp[row][column] = false;
}
}
}
//返回右下最后一个值
boolean[] lastrow = dp[dp.length-1];
return lastrow[lastrow.length-1];
}
}
思路:用Boolea类型的二维数组记录匹配状态,采用动态规划的方法解题。首先声明一个Boolean类型的二维数组dp,然后对dp进行初始化处理,接着根据状态转移的规则对String s和String p进行匹配,匹配结果填入Boolean二维数组中,直至填完该二维数组,dp最后一个元素的值即是答案,返回即可。
leetcode10.正则表达式匹配例子
(这是一个别人挺nice的训练程序,对状态转移规则不熟悉的时候可以自己用于练习。)
1.声明Boolean数组dp。dp[0][0]恒为T,行或者列都需要留空一格,因此数组的长宽分别为s.length()+1和p.length()+1。num是记录出现‘.’的次数,方便后续判断,此处仅仅先声明,具体内容后面再详细说明。
//声明boolean数组dp
boolean[][] dp = new boolean[s.length()+1][p.length()+1];
dp[0][0] = true;
int num=0;
2.初始化处理Boolean数组dp。第0行和第0列留空,因此i和j都是从1开始循环。s位于列,p位于行。记录‘.’的次数,若‘.’后紧跟着‘*’那么则可以将num的值清零,否则一直记录,如果s.length()的值小于num,表示s的长度不够,不可能完成匹配,直接返回false。
//初始化处理boolean数组
for(int i=1;i<s.length()+1;i++){
dp[i][0] = false;
}
for(int j=1;j<p.length()+1;j++){
if(p.charAt(j-1)=='*'){
dp[0][j] = dp[0][j-2];
}
}else if(p.charAt(j-1)=='.'){
dp[0][j] = dp[0][j-1];
num++;
if(j<p.length()&&p.charAt(j)=='*'){
num = 0;
}
}else{
dp[0][j] = false;
}
if(num>s.length()){
return false;
}
3.根据规则进行一一判断。将判断的值填入dp二维数组中,直至填满整个数组。因为row和column都是用于表示二维数组位置的,二维数组分别空出一行和一列,因此我们在用row和column作下标表示字符时需要-1处理。以下是具体状态转移规则:
(1)两字符不相同,直接确定为false。‘.’可当作任意字符,即任何字符与‘.’匹配都视作相同。
(2)若两字符相同,则复制dp[row-1][column-1]的值(二维数组中,左上格的值)。
(3)若p.charAt(colunm)的值为‘*’,则查看dp[row][column-2]的值(二维数组中,同一行前两列的值)。如果其值为true,那么直接复制即可,dp[row][column]的值也等于true;如果其值为false,则先对比s.charAt(row-1)【字符串当前字符】与p.charAt(colmn-2)【正则表达式上一字符】的值是否相同,若不同dp[row][column]的值为false;若相同dp[row][column]的值等于dp[row-1][column]的值。
//根据规则判断T/F
for(int row=1;row<s.length()+1;row++){
for(int column=1;column<p.length()+1;column++){
if(s.charAt(row-1)==p.charAt(column-1) || p.charAt(column-1)=='.'){
dp[row][column] = dp[row-1][column-1];
}else if(p.charAt(column-1)=='*'){
if(dp[row][column-2]==true){
dp[row][column] = true;
}else if(s.charAt(row-1)==p.charAt(column-2)||p.charAt(column-2)=='.'){
dp[row][column] = dp[row-1][column];//
}
}else if(s.charAt(row-1)!=p.charAt(column-1)){
dp[row][column] = false;
}
}
}
4.返回最后答案。声明一个lastrow去接dp二维数组的最后一行,然后去lastrow最后一个元素,它就是答案,最后返回即可。
//返回右下最后一个值
boolean[] lastrow = dp[dp.length-1];
return lastrow[lastrow.length-1];