我觉得这个问题思路基本上跟八皇后问题属于一大类,用回溯法or用动态规划去做,而所谓动态规划也无非就是对暴力破解进行剪枝,把哪些重复的计算去掉,话虽这么说,如果真在面试时碰到这种题目,那基本上还是等死吧。
写起来可以分两部,先把暴力的递归写出来,确保程序能work,然后再在暴力递归的基础上做去重,这样就可以进化出能通过oj的最终结果
递归的思路如下:
假如有s=aaab和p=a*b(肉眼一看就知道匹配true)
则其中a*可以匹配a, aa, aaa, 但是千万注意别漏掉a匹配0个字符串的情况,也就是说,即使a*b变成c*a*b,依然为true
而对这四种情况,规模降级后的子函数可以认为是 匹配 (aaab, b), (aab, b), (ab, b), (b, b)
也就是说pattern降级为a*后面的子串, 而原字符串降级为前面已匹配的字符串扣除后的右边剩下的字符串。递归的思路就是这样。
而去重的思路可以这样描述, 因为这里的所谓剩余的右边的字串,可以形式化地用原始字符串s和一个index来标识,例如ab, 可以用aaab和2来标示, aab可以用aaab和1来标识,总之一切都是为了形式化一个递归函数,那么有了这种标示方法后,就可以建立一个二维数组,arr[][], arr[i][j]用来表示 原始字符串从i开始的子串和原始pattern从j开始的子串是否匹配, 如果匹配用1表示,不匹配用0表示,而为了防止数组溢出,可以在s.length()以及p.length()的基础上分别加1,作为这个数组的维度。
思路基本就是这样,下面上java代码:
package javatest;
public class RegularExpressionMatching {
public static boolean isMatch(String s, String p) {
int[][] arr = new int[s.length()+1][p.length()+1];
return innerisMatch(s,p,0,0,arr);
}
public static boolean innerisMatch(String s, String p, int indexs, int indexp, int[][] repo) {
// System.out.println(innerisMatch("aa","a")); //false
// System.out.println(innerisMatch("aa","aa")); //true
// System.out.println(innerisMatch("aaa","aa")); //false
// System.out.println(innerisMatch("aa","a*")); //true
// System.out.println(innerisMatch("aa",".*")); //true
// System.out.println(innerisMatch("ab",".*")); //true
// System.out.println(innerisMatch("aab","c*a*b")); //true
// avoid duplicate calculation
if(indexs > s.length()){
return false;
}
if(repo[indexs][indexp]==1){
return true;
}
if(s==null || p==null){
return false;
}
if(s.substring(indexs, s.length()).length() == 0 && p.substring(indexp, p.length()).length() == 0){
repo[indexs][indexp]=1;
return true;
}
if(p.substring(indexp, p.length()).length()==0){
return false;
}
if(p.charAt(indexp)=='.'){
if(p.substring(indexp, p.length()).length()>1 && p.charAt(indexp+1)=='*'){
int si=0;
while(si<s.substring(indexs, s.length()).length()){
if(innerisMatch(s,p,indexs+si,indexp+2,repo)){
repo[indexs][indexp]=1;
return true;
}
si++;
}
if(innerisMatch(s,p,indexs+si, indexp+2, repo)){
repo[indexs][indexp]=1;
return true;
}else{
return false;
}
}else{
if(innerisMatch(s, p, indexs+1, indexp+1, repo)){
repo[indexs][indexp]=1;
return true;
}else{
return false;
}
}
}else if(p.charAt(indexp)=='*'){
if(innerisMatch(s, p, indexs, indexp+1, repo)){
repo[indexs][indexp]=1;
return true;
}else{
return false;
}
}else{
if(p.substring(indexp, p.length()).length()>1 && p.charAt(indexp+1)=='*'){
int si = 0;
if(indexs<s.length() && s.charAt(indexs)==p.charAt(indexp) ){
while(si<s.substring(indexs,s.length()).length() && s.charAt(indexs+si)==s.charAt(indexs)){
if(innerisMatch(s, p, indexs+si, indexp+2, repo )){
repo[indexs][indexp]=1;
return true;
}
si++;
}
if(innerisMatch(s, p, indexs+si, indexp+2, repo )){
repo[indexs][indexp]=1;
return true;
}else{
return false;
}
}else{
if(innerisMatch(s,p,indexs,indexp+2,repo)){
repo[indexs][indexp]=1;
return true;
}else{
return false;
}
}
}else{
if(indexs<s.length() && s.charAt(indexs) == p.charAt(indexp)){
if(innerisMatch(s, p, indexs+1, indexp+1, repo)){
repo[indexs][indexp]=1;
return true;
}else{
return false;
}
}else{
return false;
}
}
}
}
public static void main(String[] args) throws Exception {
//test cases
System.out.println(isMatch("aa","a")); //false
System.out.println(isMatch("aa","aa")); //true
System.out.println(isMatch("aaa","aa")); //false
System.out.println(isMatch("aa","a*")); //true
System.out.println(isMatch("aa",".*")); //true
System.out.println(isMatch("ab",".*")); //true
System.out.println(isMatch("aab","c*a*b")); //true
System.out.println(isMatch("ab",".*c")); //false
System.out.println(isMatch("a","ab*")); //true
System.out.println(isMatch("a",".*..a*")); //false
System.out.println(isMatch("a","a*a")); //true
System.out.println(isMatch("","b*")); //true
System.out.println(isMatch("aa","b*a")); //false
}
}