leetcode10 正则表达式匹配
正则表达式匹配
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
示例 1:
输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:s = "aa", p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:
输入:s = "ab", p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
提示:
1 <= s.length <= 20
1 <= p.length <= 30
s 只包含从 a-z 的小写字母。
p 只包含从 a-z 的小写字母,以及字符 . 和 *。
保证每次出现字符 * 时,前面都匹配到有效的字符
解题思路:
dp[i][j] 表示匹配串s的前i个字符 和 模式串p前j个字符是否匹配
dp[0][0]= true 表示 s空串和p空串 由于模式串空串可以匹配匹配串空串 设置值为true
要求dp[i][j] 是否匹配 需要区分2种情况 p[j-1] 是否为 * 字符 第j个字符的索引为j-1
1.如果 p[j-1] == '*'
这里也有2种情况
1.1 当前*和前一个字符的组合 什么也没有匹配到 这里就相当于直接把模式串的当前的组合匹配去掉
此时dp[i][j]=dp[i][j-2]
1.2 当前*和前一个字符的组合 匹配到值了 则说明匹配串当前*的前一个字符 和当前匹配串的i个字符需要匹配
match(s,p,i,j-1)
如果dp[i][j]想要匹配成功 这里有两种情况 p[j-2] 是a-z的字母的一个字符 p[j-2] 是 .
1.2.1 如果p[j-2] == '.'
则dp[i][j] = dp[i-1][j]
1.2.2 如果p[j-2] 是a-z的一个字符
则 dp[i][j] = dp[i-1][j-1]
2. p[j-1] != '*'
计算dp[i][j]是否匹配的话 需要知道当前匹配串的第i个字符和模式串的第j个字符是否相等 或者 模式串的第j个 字符为. 就是字符匹配操作 match(s,p,i,j)
dp[i][j]=dp[i-1][j-1]
两种情况都使用到了匹配函数 下面列出匹配函数
// 注意在java种获取一个字符使用 s.charAt(i) 下面为了方便写成中括号
public boolen match(String s,String p,int i, int j){
if (i < 1 || j < 1) return false;
if (p[j - 1] == '.') return true;
return s[i - 1] == p[j - 1];
}
public static boolean isMatch(String s, String p) { int m = s.length(); int n = p.length(); //dp数组 dp[i][j] 表示s前i个字符和p前j个字符匹配的结果 boolean[][] dp = new boolean[m + 1][n + 1]; //dp[0][0] s空串和p空串匹配成功 dp[0][0] = true; // dp[0][1] - dp[0][j] 要设置为false boolean数组默认初始值为false 因此不需要设置 for (int i = 0; i <= m; i++) { for (int j = 1; j <= n; j++) { if (p.charAt(j - 1) == '*') { // *表示 匹配零个或多个前面的那一个元素 // 如果匹配到字符* 则说明 *和前面字符的组合 可能匹配到 也可能什么也没匹配到 // 例如 s="" p="c*",s="c" p="c*",s="ccc" p="c*" 前面几种情况都是匹配的 // 所以这里处理第1种情况 直接丢弃这个组合的两个字符 // 根据已知条件可以知道*不可能是模式串p的第一个字符 下面的公式数组下标不可能越界 dp[i][j] = dp[i][j - 2]; // 这里处理第2种情况 让p串往前移动1个字符 和 s串的第i个字符匹配 if (match(s, p, i, j - 1)) { // 匹配成功 则s前i个字符和p前j个字符匹配的结果 // 为 s前i-1个字符和p前j-1个字符匹配的结果 // 或者 * 的前面是. 则 s前i-1个字符和p的前i个字符匹配 dp[i][j] |= dp[i - 1][j - 1]; dp[i][j] |= dp[i - 1][j]; } } else { if (match(s, p, i, j)) { dp[i][j] = dp[i - 1][j - 1]; } } } } return dp[m][n]; } public static boolean match(String s, String p, int i, int j) { if (j < 1 || i < 1) return false; // 模式串p 为. 则一定匹配 if (p.charAt(j - 1) == '.') { return true; } return s.charAt(i - 1) == p.charAt(j - 1); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
2021-06-21 css 垂直居中