LeetCode 44. Wildcard Matching(模糊匹配)
2016-05-21 04:07
531 查看
原题网址:https://leetcode.com/problems/wildcard-matching/
Implement wildcard pattern matching with support for
方法一:广度优先搜索。
方法二:非确定状态自动机,广度优先搜索。
方法三:动态规划,外层循环为pattern。
方法四:动态规划,外层循环为s
方法五:贪心法,总是假定星号不匹配,后续匹配不成功才使用星号,因此非星号总是被优先消耗掉。保存最近一个星号的位置,以及该星号所匹配到的s上的位置。
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
方法一:广度优先搜索。
public class Solution { public boolean isMatch(String s, String p) { Set<Integer> positions = new HashSet<>(); positions.add(0); for(int i=0; i<p.length(); i++) { Set<Integer> nexts = new HashSet<>(); Iterator<Integer> it = positions.iterator(); while (it.hasNext()) { Integer pos = it.next(); if (p.charAt(i) == '*') { for(int j=pos; j<=s.length(); j++) nexts.add(j); } else if (p.charAt(i) == '?') { nexts.add(pos+1); } else { if (pos < s.length() && s.charAt(pos) == p.charAt(i)) { nexts.add(pos+1); } } } positions = nexts; } return positions.contains(s.length()); } }
方法二:非确定状态自动机,广度优先搜索。
public class Solution { // pattern,直接通过pattern计算自动机的状态转移 private char[] pa; // 扣除*号之后距离目标的最短距离,如果没有考虑距离会超时。 private int[] distance; private void buildSimpleNFA(String p) { pa = p.toCharArray(); int count = 0; distance = new int[pa.length+1]; for(int i=pa.length-1; i>=0; i--) { if (pa[i] == '*') distance[i] = count; else distance[i] = ++ count; } } private Set<Integer> getClosure(Set<Integer> states) { Set<Integer> closure = new HashSet<>(); Set<Integer> currents = new HashSet<>(states); while (!currents.isEmpty()) { Set<Integer> nexts = new HashSet<>(); for(int state: currents) { closure.add(state); if (state < pa.length && pa[state] == '*') nexts.add(state+1); } currents = nexts; } return closure; } public boolean isMatch(String s, String p) { buildSimpleNFA(p); Set<Integer> states = new HashSet<>(); states.add(0); states = getClosure(states); char[] sa = s.toCharArray(); for(int i=0; i<sa.length; i++) { Set<Integer> nexts = new HashSet<>(); for(int state: states) { if (state>=pa.length || i+distance[state]>sa.length) continue; if (pa[state] == '*') nexts.add(state); if (pa[state] == '*' || pa[state] == '?' || pa[state] == sa[i]) nexts.add(state+1); } states = getClosure(nexts); } return states.contains(pa.length); } }
方法三:动态规划,外层循环为pattern。
public class Solution { public boolean isMatch(String s, String p) { if (s == null && p == null) return true; if (s == null || p == null) return false; char[] sa = s.toCharArray(); char[] pa = p.toCharArray(); // matched[i][j]表示是否成功匹配到p的第i个(不含)和s的第j个(不含) boolean[][] matched = new boolean[pa.length+1][sa.length+1]; matched[0][0] = true; for(int i=1; i<=pa.length; i++) { matched[i][0] = pa[i-1] == '*' && matched[i-1][0]; for(int j=1; j<=sa.length; j++) { if (pa[i-1] == '*') matched[i][j] = matched[i][j-1] || matched[i-1][j]; else if (pa[i-1] == '?') matched[i][j] = matched[i-1][j-1]; else if (pa[i-1] == sa[j-1]) matched[i][j] = matched[i-1][j-1]; } } return matched[pa.length][sa.length]; } }
方法四:动态规划,外层循环为s
public class Solution { public boolean isMatch(String s, String p) { if (s.length()==0 && p.length()==0) return true; if (p.length()==0) return false; char[] sa = s.toCharArray(); char[] pa = p.toCharArray(); boolean[][] matched = new boolean[sa.length+1][pa.length+1]; matched[0][0] = true; for(int j=1; j<=pa.length; j++) { if (pa[j-1]=='*') matched[0][j] = matched[0][j-1]; } for(int i=1; i<=sa.length; i++) { matched[i][0] = pa[0] == '*' && matched[i-1][0]; for(int j=1; j<=pa.length; j++) { if (pa[j-1] == '*') matched[i][j] = matched[i-1][j] || matched[i][j-1]; else if (pa[j-1] == '?') matched[i][j] = matched[i-1][j-1]; else if (pa[j-1] == sa[i-1]) matched[i][j] = matched[i-1][j-1]; } } return matched[sa.length][pa.length]; } }
方法五:贪心法,总是假定星号不匹配,后续匹配不成功才使用星号,因此非星号总是被优先消耗掉。保存最近一个星号的位置,以及该星号所匹配到的s上的位置。
public class Solution { public boolean isMatch(String s, String p) { char[] sa = s.toCharArray(); char[] pa = p.toCharArray(); int si = 0, pi = 0; // ls表示最近一个星号匹配到的s的位置 // lp表示最近一个星号的位置 int ls = -1, lp = -1; while (si < sa.length) { if (pi < pa.length && (pa[pi] == '?' || sa[si] == pa[pi])) { si ++; pi ++; } else if (pi < pa.length && pa[pi] == '*') { ls = si; lp = pi ++; } else if (ls >= 0) { si = ++ ls; pi = lp + 1; } else { return false; } } while (pi < pa.length && pa[pi] == '*') pi ++; return pi == pa.length; } }
相关文章推荐
- 大数据和Android
- Mvp架构的使用
- 【三分法/数学公式】B君的圆锥【51nod】【BSG白山极客挑战赛】
- Bigbluebutton中文乱码问题
- Bigbluebutton安装过程
- [置顶] Android自定义View(二、深入解析自定义属性)
- Android自定义View(二、深入解析自定义属性)
- 蓝桥杯国赛前一周深夜思索
- 辛星浅析yaml
- 使用GSON解析一个复杂的json
- strtok 和 sscanf 结合输入
- 统计学 入门基础概念篇 - Descriptive Statistics: Quantitative Measures(个人笔记)
- Python之路,Day2
- Win10 中git的配置及使用
- 关于爆栈问题——手动加栈
- 自我检测3
- FlexboxLayout
- 原生js+css3实现图片自动切换,图片轮播
- Android开源工具项目集合
- 【dp基础课程】矩阵取数问题+最大子段和+最长公共子序列(LCS)【51nod】