[LeetCode]44. Wildcard Matching 深入浅出讲解和代码示例

1、汇总概要

本题是模式匹配问题,解题思路涵盖了递归、以及匹配算法的知识点

2、题目

Implement wildcard pattern matching with support for '?' and '*'.

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

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", "*") ? true
isMatch("aa", "a*") ? true
isMatch("ab", "?*") ? true
isMatch("aab", "c*a*b") ? false

3、审题

该题是模式匹配问题。

4、解题思路


1、原串(s)和模式串(p)匹配规则考虑时,涉及到三种基本情况,以及其任意组合:

1) 模式串当前是字符时(p[j]是char):相等则继续比较下一个,不相等则返回不匹配(false)
2) p[j] == ‘?’时:当做相等,继续比较下一个;
3) p[j] == '*'时:跳过*,s中当前位置查看是否有与p[j+1]匹配的元素,这种情况较复杂。

以s=' abcdefga', p=' ab?*g*'为例,示意图讲解如下:

[LeetCode]44. Wildcard Matching 深入浅出讲解和代码示例_第1张图片

Step1:初始i=0, j=0,顺序比较s[i]和p[j], 相同时指针指向下一个,继续比较;不等时,返回false;
Step2:p[j] == '?'时,任意字符与其匹配,指针指向下一个继续比较;
Step3:p[j] == '*'时(j=3),跳过*,比较*的下一个字符p[4](即'g'),从s[3]开始,查找后面的字符是否有'g'(p[6]),
     1)若能找到, 则从其位置开始,继续循环执行Step1~Step3;
     2)若找不到,返回false;

以上是基本思路,确定比较规则后,代码中循环遍历即可。

2、还有一种较复杂的情况需考虑,在Step3中比较*后面的字符时,如果匹配到多个,应该以哪个为准?这种情况容易被忽略。

举例:
1)当s='abab', p='*abab'时:
'*'后面的'a'在s中多个位置都可以找到(i=0,i=2)那么应该以哪个位置为准呢:
以i=0为准(即从i=0的下一个位置开始,继续下一个比较),结果是true;
以i=2为准,结果是false;
结论:本例中应该以第一次匹配到的位置为准,即i=0;
2)s='abab', p='*ab'时,以1)例中同样的方式分析,应该以最后一次匹配到的位置为准,即i=2;
所以,这里有个动态规划的思路,在处理时,并不能确定应该是以第一次匹配到的位置为准,还是最后一次,或者是中间的某一次匹配到的位置。
妥善的处理方法是,遍历所有s串中可以匹配到*下一个字符的位置,止到结果是true。
[当存在多个*时,仍然用这种思路处理]

动态规划的常用实现方法是递归函数(实现代码见下)。

5、代码示例 - Java
public class WildcardMatching {
	public boolean subMatch(String s, String p,int iStart,int jStart) throws InterruptedException{
		int i = iStart;
		int j = jStart;
		int lens = s.length();
		int lenp = p.length();
		System.out.println("\n\nrecursion ====== "+lens+" "+lenp);
		boolean res = false;
		while(j j++, and break;(no need to recursion)
				 * if next is ? =>  i++(start index skep 1),j++;
				 */
				if(j=lens-1){//? match the last one in s
							while(j=lenp){
								res = true;
								return res;
							}
						}
						continue; //go to loop again
					}else{
						//go to recursion branch
						while(i= lenp; one/multiple * in the tail of p
					res = true;
					return res;
				}
			} //end if(*)
			if(i=lenp-1){
					res = true;
				}else{
					res = false;
				}
				break;
			}else if(i==lens-1 && j==lenp-1){//both get the end
				if(s.charAt(i)==p.charAt(j) || p.charAt(j) == '?'){
					res = true;
					return res;
				}
			}
			if(s.charAt(i)==p.charAt(j)||p.charAt(j)=='?'){ //loop to compare
				i++;
				j++;
			}else{
				res = false;
				break;
			}
		}
		return res;
	}
	
	public boolean isMatch(String s, String p) throws InterruptedException{
		boolean res = subMatch(s,p,0,0);
		return res;
	}
	
	public static void main(String[] args) throws InterruptedException{
//		String s = "abcdefga";
//		String p = "ab?*g*a";
		
//		String s = "abcdefga";
//		String p = "ab?*g*";
		
//		String s = "aaaba";
//		String p = "a*?a*b*a";
//		String p = "aaa***ba";
		
//		String s = "abab";
//		String p = "*?*ba*?*";
//		String p = "***ab***";
		
//		String s = "abc12abc1d1dabc1d1e";
//		String p = "*abc?d?*e";
		
		String s = "abab1";
		String p = "*?*ba*??*";
		
//		String s = "ab";
//		String p = "??";
		
		WildcardMatching wm = new WildcardMatching();
		System.out.println(s+"\n"+p+"\n");
		boolean res = wm.isMatch(s,p);
		System.out.println("\nres: "+res);
	}
}

注:可参考main中的s、p的赋值做单元测试;


---------------------------------------------------------------------------------------------------

本文链接:http://blog.csdn.NET/karen0310/article/details/75053593

请尊重作者的劳动成果,转载请注明出处!

---------------------------------------------------------------------------------------------------



你可能感兴趣的:(算法)