原题:
Implement regular expression matching with support for '.'
and '*'
.
'.' Matches any single character. '*' Matches zero or more of the preceding element. The matching should cover the entire input string (not partial). The function prototype should be: bool isMatch(const char *s, const char *p) Some examples: isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "a*") → true isMatch("aa", ".*") → true isMatch("ab", ".*") → true isMatch("aab", "c*a*b") → true
即判断给定字符串是否符合正则表达式。这里正则表达式包括符号'.','*',前者表示可以和任意单个字符匹配,后者表示后者前面的字符可以匹配0到多个。两者放到一起,代表可以匹配任何长度的任何字符。
思考过程:
很难确定'*'和多少个字符匹配合适,一筹莫展,看了别人的博客,受到启发。用递归函数,动态规划思想,遍历所有可能个数的字母和'*'匹配,直至匹配成功,否则返回false。
解题思路:
详情看代码注释。这里要注意字符索引越界问题。在s遍历结束后要继续判断,因为如果p剩下"a*"这样的字符,它们也是匹配的。
public boolean isMatch(String s, String p){
if (p.isEmpty()) return s.isEmpty();//递归结束的标志
if (p.length() == 1) return ((s.length() == 1 && p.charAt(0) == '.') || p.equals(s));//防止后面p,charAt(1)越界,同时也是递归结束的标志
if (p.charAt(1) == '*') return (isMatch(s,p.substring(2)) || (!s.isEmpty() &&(s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') && (isMatch(s.substring(1),p))));//第二个字母为'*'的情况:要么在p中越过p.charAt(0),p.charAt(1),要么首字母匹配情况下,p不变,s匹配下一个字母。
else if (!s.isEmpty() && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.')) return isMatch(s.substring(1), p.substring(1));//首字母匹配,而且第二个字母不是'*',递归
else return false;//第二个字母不是'*'而且首字母不匹配,返回false
}