WildcardMatching和Regex,通配符匹配和正则表达式匹配
WildcardMatching:通配符匹配
算法分析:
1. 二个指针i, j分别指向字符串、匹配公式。
2. 如果匹配,直接2个指针一起前进。
3. 如果匹配公式是*,在字符串中依次匹配即可。
注意记录上一次开始比较的位置
Implement wildcard pattern matching with support for '?'
and '*'
'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).
Some examples: isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "*") → true isMatch("aa", "a*") → true isMatch("ab", "?*") → true isMatch("aab", "c*a*b") → false
public class WildcardMatching { public boolean isMatch(String s, String p) { if (s == null || p == null) { return false; } int indexS = 0; int indexP = 0; int lenS = s.length(); int lenP = p.length(); int preP = -1;//记录通配符为*时通配字符串的下标 int preS = -1;//记录通配符为*时要匹配的字符串下标 while (indexS < lenS) { //非*匹配时,indexS和indexP同时移动 if (indexP < lenP && (p.charAt(indexP)==s.charAt(indexS)||p.charAt(indexP)=='?')) { indexP++; indexS++; } //碰到*,记录此时p,s的下标 else if (indexP < lenP && p.charAt(indexP) == '*') { preS = indexS; preP = indexP; // p比较指针后移,假设*匹配空字符串 indexP++; } else if (preP != -1)//尝试匹配* { indexP = preP;//p回退到*位置 indexP++; preS++;//尝试匹配*,每次移动一个字符,然后比较p的*后面字符和s剩下的字符,如果不匹配,回退到*的位置 indexS = preS; } else { return false; } } while (indexP < lenP) { if (p.charAt(indexP) != '*') { return false; } indexP++; } return true; } //通过例子aab和*ab来模拟过程 public static void main(String[] args) { WildcardMatching wm = new WildcardMatching(); System.out.println(wm.isMatch("aab", "*ab")); } }
Regex:正则表达式匹配
问题描述: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
算法分析:.*可以匹配任意字符串,例如ab匹配.*,不是说让.匹配完a然后再去匹配*,而是*匹配的是.,也就是说(.*)==(..........),所以.*匹配所有字符串。
利用动态规划,对于匹配字符串p,讨论三种情况,p长度为0,p长度为1,p的长度大于1(p的第二字符串为*,p的第二个字符串不为*)
//动态规划 public class Regex2 { public boolean isMatch(String s, String p) { // p长度为0,边界条件。 if (p.length() == 0) { return s.length() == 0; } // p长度为1,边界条件。 if (p.length() == 1) { // s长度为0 if (s.length() < 1) { return false; } //首元素匹配有两种情况 // 如果p为.则s第一个元素和p一定匹配,如果p的第一个元素和s的第一元素相同,也一定匹配。 else if ((p.charAt(0) != s.charAt(0)) && (p.charAt(0) != '.')) { return false; } // 否则除了第一个匹配的元素外,比较其他的元素,动态规划的思想。 else { return isMatch(s.substring(1), p.substring(1)); } } // p的第二个元素不是*,*代表0个或多个前面的元素 if (p.charAt(1) != '*') { if (s.length() < 1) { return false; } else if ((p.charAt(0) != s.charAt(0)) && (p.charAt(0) != '.')) { return false; } else { return isMatch(s.substring(1), p.substring(1)); } } else //p的第二个元素是* { //*代表0个前面的元素 if (isMatch(s, p.substring(2))) { return true; } //*代表一个或多个前面的元素 //遍历s,如果s的i元素等于p的第一个元素,或者p的第一个元素为.,匹配s的i+1和p的第三个元素后的字符串 for(int i = 0; i<s.length() && (s.charAt(i) == p.charAt(0) || (p.charAt(0) == '.')); i ++ ) { if(isMatch(s.substring(i + 1), p.substring(2))) { return true; } } return false; } } public static void main(String[] args) { Regex2 reg2 = new Regex2(); System.out.println(reg2.isMatch("aaba", ".*")); } }