Open songyy5517 opened 1 year ago
思路1:动态规划
定义二维布尔数组 f,f[i][j] 表示字符串 s 的前 i 个字符与正则表达式 p 的前 j 个字符是否匹配
初始化 & 考虑特殊情况:当正则表达式为空时, (1) 若字符串为空,则二者匹配,即 f[0][0] = true; (2) 若字符串非空,则二者不匹配,即 f[i][0] = false (i≠0);
匹配字符串 s 与正则表达式 p,即需要计算出 f[s.length()][p.length()] 的值,因此我们需要从 f[0][0] 出发计算每个 f 中的值。根据正则表达式 p 的当前(位置j)字符是否为 '*'
, 有两种不同的匹配情况:
(1) 若 p 当前(位置j)字符不为 '*'
,则直接对比 p 与 s (位置i)当前的字符是否匹配;
(2) 若 p 当前(位置j)字符为 '*'
,则分两种情况:
'*'
前一个字符(位置j-1)与 s 的当前字符(位置i)匹配,则继续看 s 前一个字符是否也匹配,即 f[i][j] = f[i-1][j];'*'
前一个字符(位置j-1)与 s 的当前字符(位置i)匹不匹配,直接跳过 p 中的'*'
组合,即 f[i][j] = f[i][j-2]。返回最终的匹配结果 f[s_len][p_len]
复杂度分析
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param str string字符串
* @param pattern string字符串
* @return bool布尔型
*/
public boolean match (String str, String pattern) {
// write code here
// 分析:动态规划
// 1. 异常处理
if (str == null || pattern == null)
return false;
// 2. 状态定义&初始化
// f[i][j]: str[0:i]能否与pattern[0:j]匹配成功
// f[i][0]一定为false (i!=0)
boolean[][] f = new boolean[str.length() + 1][pattern.length() + 1];
f[0][0] = true;
// 3. 自底向上计算各个状态
for (int i = 0; i < str.length() + 1; i++){
for (int j = 1; j < pattern.length() + 1; j++){
// 正则表达式的当前字符不为'*'
if (pattern.charAt(j - 1) != '*'){
// 当前字符匹配成功,则进行状态转移
if (i > 0 && (pattern.charAt(j-1) == str.charAt(i - 1) || pattern.charAt(j-1) == '.'))
f[i][j] = f[i-1][j-1];
// 不匹配,则将状态值置为false
else
f[i][j] = false;
}
// 正则表达式的当前字符为'*'
else {
// 无论匹配与否,直接跳过'*'组合
if (j >= 2)
f[i][j] = f[i][j-2];
// 匹配'*'组合
if (j >= 2 && i >= 1 && (pattern.charAt(j-2) == '.' || pattern.charAt(j-2) == str.charAt(i-1)))
f[i][j] = f[i-1][j] || f[i][j];
}
}
}
return f[str.length()][pattern.length()];
}
}
思路2:递归
""
时,表示匹配成功,返回true;按从后往前的顺序,依次匹配 s 和 p:[递归]
(1) 若 p 当前字符不为 '*'
,比较 s 与 p 的当前字符是否匹配:
(2) 若 p 当前字符为 '*'
,则看 p 的前一个字符是否可与 s 的当前字符匹配:
'*'
组合的情况,即返回 isMatch(s.subsring(0, s_len-1), p) || isMatch(s, p.substring(0, p_len-2));'*'
组合,即返回 isMatch(s, p.substring(0, p_len-2));import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param str string字符串
* @param pattern string字符串
* @return bool布尔型
*/
public boolean match (String str, String pattern) {
// write code here
// 分析:递归,自顶向下匹配字符串
// 递归出口
if (str.equals("") && pattern.equals(""))
return true;
if (!str.equals("") && pattern.equals(""))
return false;
// 正则表达式当前字符不为'*'
int p_len = pattern.length();
int s_len = str.length();
// 正则表达式当前字符不为'*'
if (pattern.charAt(p_len-1) != '*'){
if (s_len > 0 && (pattern.charAt(p_len-1) == '.' || pattern.charAt(p_len-1) == str.charAt(s_len-1)))
return match(str.substring(0,s_len-1), pattern.substring(0, p_len-1));
else
return false;
}
// 正则表达式当前字符为'*'
else{
// 匹配'*'组合:匹配||直接跳过
if (p_len > 1 && s_len > 0 && (pattern.charAt(p_len - 2) == str.charAt(s_len-1) || pattern.charAt(p_len - 2) == '.'))
return match(str.substring(0,s_len-1), pattern) || match(str, pattern.substring(0,p_len-2));
// 没有匹配成功则直接跳过'*'组合
return match(str, pattern.substring(0, p_len-2));
}
}
}
2023/1/31
2023/2/1
2023/11/27
*
划分匹配情况;*
组合时,可以选择直接跳过。2023/11/29
if (i > 0 && (cur_p == '.' || cur_p == str.charAt(i - 1)))
而不是:if (cur_p == '.' || (i > 0 && cur_p == str.charAt(i - 1)))
2024/3/23 2024/4/5
请实现一个函数用来匹配包含
'. '
和'*'
的正则表达式。模式中的字符'.'
表示任意一个字符,而'*'
表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"
与模式"a.a"
和"ab*ac*a"
匹配,但与"aa.a"
和"ab*a"
均不匹配。示例 1:
示例 2:
示例 3:
示例 4:
示例 5:
s
可能为空,且只包含从a-z
的小写字母。p
可能为空,且只包含从a-z
的小写字母以及字符.
和*
,无连续的'*'
。分析 这道题考察的是字符串匹配。不同长度的字符串可以看成是不同的状态,因此字符串匹配涉及到状态之间的转移,所以我们可以考虑使用动态规划来解决问题。