44、 Wildcard Matching (Hard)

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
题意就是实现智能匹配,?可以匹配任何一个字符,*可以匹配任何数目的任何字符。关键在于对*的处理。这个题是典型的动态规划题,《算法导论》里有,只要注意*在矩阵中的处理即可。自己当时不想用动态规划实现,想到一种自认为比较绝妙的方法,就是把要匹配的字符串按照*分割,然后按照分割次序依次和待匹配的字符串匹配,匹配成功一个就纪录下当前位置,下一个分割的字符串就从当前位置的下一个位置继续开始匹配。如果待匹配的字符串已经到终点而要匹配的分割字符串还没匹配完,就说明匹配失败了。大概是一种贪心的算法思想,而且感觉实现起来不难。结果,我就掉进了一个大坑,各种奇形怪状的测试用例让我对程序的逻辑进行修补,失败了十几次,眼睁睁的看着1807个测试用例的通过个数从500涨到650,再到700、800、1200、1600、1750、1780........最后终于完全AC,这个时候我几乎已经看不懂我的代码了,而且悲剧的是实现时间也只超过了18%的人,如果用动态规划则肯定能超过一半的人。看来用空间换时间还是对的。总之还是要把自己的看不懂但历尽千辛万苦最后还是通过的代码贴出来,动态规划实现的代码网上到处都是,就不贴了。

import java.util.Scanner;

public class Test {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		while (true) {
			String s = in.next();
			String p = in.next();
			System.out.println(isMatch(s, p));
		}
	}

	public static boolean isMatch(String s, String p) {
		if (s.length() == 0 && p.length() == 0) {
			return true;
		}
		char[] a = s.toCharArray();
		int skip = 0;

		String[] mline = p.split("\\*");

		int mlength = 0;
		for (int i = 0; i < mline.length; i++) {
			if (!mline[i].equals("")) {
				mlength++;
			}
		}

		int number = 0;
		char[] c = p.toCharArray();
		for (int i = 0; i < c.length; i++) {
			if (c[i] != '*') {
				number++;
			}
		}

		if (number > s.length()) {
			return false;
		}

		if (mline.length == 0) {
			return true;
		}
		if (mlength == 1) {
			boolean flag1 = false;
			boolean seenflag = false;
			boolean fflag = false;
			boolean bflag = false;

			for (char w : p.toCharArray()) {
				if (w == '*') {
					flag1 = true;
					if (!seenflag) {
						fflag = true;
					} else {
						bflag = true;
					}
				} else {
					seenflag = true;
				}
			}

			if (!flag1 && p.length() != s.length()) {
				return false;
			}
			int snumber = 0;
			for (int i = 0; i < mline.length; i++) {
				if (mline[i].length() > 0) {
					snumber = i;
				}
			}

			char[] bb = mline[snumber].toCharArray();

			boolean flag = false;
			if (fflag && bflag) {

				for (int i = 0; i <= a.length - bb.length; i++) {
					for (int j = 0; j < bb.length; j++) {
						if (a[i + j] != bb[j] && bb[j] != '?') {
							break;
						} else {
							if (j == bb.length - 1) {
								flag = true;
								break;
							}
						}
					}
				}

			}

			else if (fflag && !bflag) {
				int i = a.length - 1;
				int j = bb.length - 1;
				while (j >= 0 && i >= 0 && (a[i] == bb[j] || bb[j] == '?')) {
					if (j == 0) {
						flag = true;
					}
					i--;
					j--;
				}
			} else if (!fflag && bflag) {

				System.out.println("4");
				for (int i = 0; i < bb.length; i++) {
					if (bb[i] == a[i] || bb[i] == '?') {
						if (i == bb.length - 1) {
							flag = true;
							break;
						}
					} else {
						break;
					}
				}
			} else {
				for (int i = 0; i < bb.length; i++) {
					if (bb[i] == a[i] || bb[i] == '?') {
						if (i == bb.length - 1 && i == a.length - 1) {
							flag = true;
							break;
						}
					} else {
						break;
					}
				}
			}

			if (!flag) {
				return false;
			}

			if (flag) {
				return true;
			}

		}

		// *分割的第一个字符串和最后一个字符串也必须要判断。
		for (int i = 0; i < mline.length; i++) {
			System.out.println("skip:" + skip);
			char[] b = mline[i].toCharArray();
			if (b.length == 0) {
				continue;
			}
			if (i == 0) {
				System.out.println("0判断");
				boolean temp = false;
				for (int k = 0; k < b.length; k++) {				
					System.out.println("K判断"+k+" ak:"+a[k]+" bk:"+b[k]);
					if (b[k] == a[k] || b[k] == '?') {
						
						if (k == b.length - 1) {
							temp = true;
						}
					}
					else{
						break;
					}
				}
				if (!temp) {
					return false;
				}

			}

			else if (i == mline.length - 1) {
				if (!p.substring(p.length() - 1, p.length()).equals("*")) {
					System.out.println("!!*");
					boolean temp = false;
					for (int k = 0; k < b.length; k++) {
						if ((b[b.length - 1 - k] == a[a.length - 1 - k])
								|| b[b.length - 1 - k] == '?') {
							if (k == b.length - 1) {
								temp = true;
							}
						} else {
							break;
						}
					}
					System.out.println("skiplalal:   "+skip+"   "+s.length());
					if (!temp || skip ==s.length()||(skip<s.length()&&skip+b.length>s.length())) {
						return false;
					} else {
						System.out.println("lallaalwwww");
						return true;
					}
				} else {
					System.out.println("*");
					// 最后一个是*,跳跃skip
					for (int k = skip; k < s.length(); k++) {
						boolean flag = false;
						for (int j = 0; j < b.length; j++) {
							if (j + k < a.length) {
								if (b[j] == a[j + k] || b[j] == '?') {
									if (j == b.length - 1) {
										flag = true;
									}
								} else {
									break;
								}
							} else {
								return false;
							}
						}
						if (flag) {
							skip = k;
							// System.out.println("wen");
							return true;
						}
					}
					return false;

				}
			}

			boolean matchflag = false;
			if (skip < s.length()) {
				for (int k = skip; k < s.length(); k++) {
					// System.out.println("k:" + k);
					boolean flag = false;
					for (int j = 0; j < b.length; j++) {
						if (j + k < a.length) {
							if (b[j] == a[j + k] || b[j] == '?') {
								if (j == b.length - 1) {
									flag = true;
									matchflag = true;
								}
							} else {
								break;
							}
						} else {
							return false;
						}
					}
					if (flag) {
						skip += (k - skip + b.length);
						break;
					}
				}
				if(!matchflag){
					return false;
				}
				
			} else {
				return false;
			}

		}

		/*
		 mississippi 
		 m*i*si*si*si*pi
		 */

		return false;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值