请实现一个函数用来匹配包含’.
‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。示例 1: 输入: s = “aa” p = “a” 输出: false 解释: “a” 无法匹配 “aa” 整个字符串。
示例 2: 输入: s = “aa” p = “a*” 输出: true 解释: 因为 ‘*’ 代表可以匹配零个或多个前面的那一个元素,
在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。示例 3: 输入: s = “ab” p = “." 输出: true 解释: ".”
表示可匹配零个或多个(’*’)任意字符(’.’)。示例 4: 输入: s = “aab” p = “cab” 输出: true 解释: 因为 ‘*’ 表示零个或多个,这里 ‘c’ 为 0
个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。示例 5: 输入: s = “mississippi” p = “misisp*.” 输出: false s 可能为空,且只包含从
a-z 的小写字母。 p 可能为空,且只包含从 a-z 的小写字母以及字符 . 和 ,无连续的 '’。
题解:
这种匹配思路其实就是不断地减掉s和p的可以匹配首部,直至一个或两个字符串被减为空的时候,根据最终情况来得出结论。
如果只是两个普通字符串进行匹配,按序遍历比较即可:
if( s.charAt(i) == p.charAt(i) ) 如果正则表达式字符串p只有一种"."一种特殊标记,依然是按序遍历比较即可:
if( s.charAt(i) == p.charAt(i) || p.charAt(i) == ‘.’ )
上述两种情况实现时还需要判断字符串长度和字符串判空的操作。但是,"*"这个特殊字符需要特殊处理,当p的第i个元素的下一个元素是星号 时会有两种情况:
i元素需要出现0次,我们就保持s不变,将p的减掉两个元素,调用isMatch。例如s:bc、p:abc,我们就保持s不变,减掉p的"a",调用isMatch(s:bc,p:bc)。
i元素需要出现一次或更多次,先比较i元素和s首元素,相等则保持p不变,s减掉首元素,调用isMatch。例如s:aabb、p:abb,就保持p不变,减掉s的首元素,调用isMatch(s:abb,p:abb)。
此时存在一些需要思考的情况,例如s:abb、p:a*abb,会用两种方式处理:
按照上述第二种情况比较i元素和s首元素,发现相等就会减掉s的首字符,调用isMatch(s:bb,p:a*abb)。在按照上述第一种情况减去p的两个元素,调用isMatch(s:bb,p:abb),最终导致false。
直接按照上述第一种情况减去p的两个元素,调用isMatch(s:abb,p:abb),最终导致true。
所以说这算是一种暴力方法,会将所有的情况走一遍,看看是否存在可以匹配的情况。
class Solution {
public boolean isMatch(String s, String p) {
//如果正则串p为空字符串s也为空这匹配成功,如果正则串p为空但是s不是空则说明匹配失败
if (p.isEmpty())return s.isEmpty();
//判断s和p的首字符是否匹配,注意要先判断s不为空
boolean headMatched=!s.isEmpty()&&(s.charAt(0)==p.charAt(0)||p.charAt(0)=='.');
if (p.length()>=2&&p.charAt(1)=='*'){//如果p的第一个元素的下一个元素是*
//则分别对两种情况进行判断
return isMatch(s,p.substring(2))||
(headMatched&&isMatch(s.substring(1),p));
}else if (headMatched){//否则,如果s和p的首字符相等
return isMatch(s.substring(1),p.substring(1));
}else {
return false;
}
} }
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof