LeetCode 10. Regular Expression Matching(正则表达式匹配)

原题网址:https://leetcode.com/problems/regular-expression-matching/

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

方法一:有限状态自动机。

public class Solution {
    Map> nfa = new HashMap<>();
    int accept = 0;
    private Set getTransfers(int state) {
        Set transfers = nfa.get(state);
        if (transfers == null) {
            transfers = new HashSet();
            nfa.put(state, transfers);
        }
        return transfers;
    }
    private Set getEpsilonStates(int state) {
        Set states = new HashSet<>();
        Iterator it = getTransfers(state).iterator();
        while (it.hasNext()) {
            Transfer transfer = it.next();
            if (transfer.ch == (char)0) states.add(transfer.next);
        }
        return states;
    }
    private Set getNextStates(int state, char ch) {
        Set states = new HashSet<>();
        Iterator it = getTransfers(state).iterator();
        while (it.hasNext()) {
            Transfer transfer = it.next();
            if (transfer.ch == ch || transfer.ch == '.') states.add(transfer.next);
        }
        return states;
    }
    private void addTransfer(int state, Transfer transfer) {
        Set transfers = getTransfers(state);
        transfers.add(transfer);
    }

    private void buildNFA(String re) {
        int state = 0;
        for(int i=0; i getClosure(Set states) {
        Set closure = new HashSet<>();
        closure.addAll(states);

        Set found = new HashSet<>();
        found.addAll(states);
        
        while (!found.isEmpty()) {
            Set epsilons = new HashSet<>();
            Iterator it = found.iterator();
            while (it.hasNext()) {
                int state = it.next();
                epsilons.addAll(getEpsilonStates(state));
            }
            Iterator eit = epsilons.iterator();
            found = new HashSet<>();
            while (eit.hasNext()) {
                int state = eit.next();
                if (closure.contains(state)) continue;
                closure.add(state);
                found.add(state);
            }
        }
        
        return closure;
    }
    
    public boolean isMatch(String s, String p) {
        buildNFA(p);
        Set states = new HashSet<>();
        states.add(0);
        for(int i=0; i closure = getClosure(states);
            Set nexts = new HashSet<>();
            Iterator it = closure.iterator();
            while (it.hasNext()) {
                nexts.addAll(getNextStates(it.next(), s.charAt(i)));
            }
            states = nexts;
        }
        states = getClosure(states);
        return states.contains(accept);
    }
}

class Transfer {
    char ch;
    int next;
    Transfer(char ch, int next) {
        this.ch = ch;
        this.next = next;
    }
    
    @Override
    public String toString() {
        return "(" + ch + ", " + next + ")";
    }
}

另一种实现:

public class Solution {
/*
"aa"
"a"
"aa"
"a*"
"aa"
"aaa"
"aa"
".*"
"a"
"ab*"
"a"
".*..a*"
*/
    public boolean isMatch(String s, String p) {
        NFA nfa = new NFA();
        Integer start = nfa.addState();
        Integer accept;
        Integer current = start;
        for(int i=0; i states = new HashSet<>();
        states.add(0);
        states = nfa.getClosure(states);
        // System.out.printf("Begins, states=%s\n", states);
        for(int i=0; i nexts = nfa.getNexts(states, s.charAt(i));
            states = nfa.getClosure(nexts);
        }
        return states.contains(accept);
    }
}
class NFA {
    private Map>> transfers = new HashMap<>();
    void print() {
        for(Integer state: transfers.keySet()) {
            Map> transfer = transfers.get(state);
            for(Character ch: transfer.keySet()) {
                System.out.printf("[%s]--%s-->%s\n", state, ch, transfer.get(ch));
            }
        }
    }
    
    int states = 0;
    Integer addState() {
        return states++;
    }
    
    void addNext(Integer state, Character ch, Integer next) {
        Map> transfer = transfers.get(state);
        if (transfer == null) {
            transfer = new HashMap>();
            transfers.put(state, transfer);
        }
        Set nexts = transfer.get(ch);
        if (nexts == null) {
            nexts = new HashSet<>();
            transfer.put(ch, nexts);
        }
        nexts.add(next);
    }
    
    Set getClosure(Set states) {
        Set closure = new HashSet<>();
        closure.addAll(states);
        Set currents = states;
        boolean found;
        do {
            found = false;
            currents = getNexts(currents, null);
            for(Integer state: currents) {
                if (!closure.contains(state)) {
                    closure.add(state);
                    found = true;
                }
            }
        } while (found);
        return closure;
    }
    Set getNexts(Set states, Character ch) {
        Set results = new HashSet<>();
        for(Integer state: states) {
            Map> transfer = transfers.get(state);
            if (transfer == null) continue;
            Set nexts;
            if (ch == null) {
                nexts = transfer.get(ch);
                if (nexts == null) continue;
            } else {
                nexts = new HashSet();
                Set chnext = transfer.get(ch);
                if (chnext != null) nexts.addAll(chnext);
                Set dot = transfer.get('.');
                if (dot != null) nexts.addAll(dot);
            }
            results.addAll(nexts);
        }
        return results;
    }
}

方法二:简化的状态机,广度优先搜索,以p为外层循环。

public class Solution {
    public boolean isMatch(String s, String p) {
        Set states = new HashSet<>();
        states.add(0);
        for(int i=0; i nexts = new HashSet<>();
            for(int state: states) {
                if (re == '.') {
                    if (star) {
                        for(int j=state; j<=s.length(); j++) {
                            nexts.add(j);
                        }
                    } else {
                        nexts.add(state+1);
                    }
                } else {
                    if (star) {
                        for(int j=state; j<=s.length(); j++) {
                            nexts.add(j);
                            if (j

另一种实现,这种实现最简单:

public class Solution {
    public boolean isMatch(String s, String p) {
        Set states = new HashSet<>();
        states.add(0);
        char[] sa = s.toCharArray();
        char[] pa = p.toCharArray();
        for(int i=0; i nexts = new HashSet<>();
            for(int state: states) {
                if (state >= sa.length) {
                    if (star) nexts.add(state);
                } else if (star) {
                    nexts.add(state);
                    for(int j=state; j


另一种实现:

public class Solution {
    /*
    这些case都很重要,很多BUG!!!
""
""
"aa"
"a"
"aa"
"a*"
"aa"
"aaa"
"aa"
".*"
"a"
"ab*"    
*/
    public boolean isMatch(String s, String p) {
        int n = s.length();
        int[] states = new int[n+1];
        int[] nexts = new int[n+1];
        boolean[] reached = new boolean[n+1];
        reached[0] = true;
        int size = 0;
        states[size++] = 0;
        for(int i=0; i

方法三:广度优先搜索,简化的自动机,外层循环是s

public class Solution {
    private Set closure(Set states, char[] pa) {
        Set closure = new HashSet<>();
        Set found = new HashSet<>(states);
        while (!found.isEmpty()) {
            Set nexts = new HashSet<>();
            for(int f: found) {
                closure.add(f);
                if (f states = new HashSet<>();
        states.add(0);
        states = closure(states, pa);
        for(int i=0; i nexts = new HashSet<>();
            for(int state: states) {
                if (state >= pa.length) continue;
                if ((pa[state] == '.' || pa[state] == sa[i]) && state < pa.length-1 && pa[state+1] == '*') {
                    nexts.add(state);
                } else if (pa[state] == '.' || pa[state] == sa[i]) {
                    nexts.add(state+1);
                }
            }
            states = closure(nexts, pa);
        }
        return states.contains(pa.length);
    }
}

方法四:动态规划,以p为外层循环。

public class Solution {
    public boolean isMatch(String s, String p) {
        char[] sa = s.toCharArray();
        char[] pa = p.toCharArray();
        boolean[] match = new boolean[sa.length + 1];
        match[0] = true;
        for(int i = 1; i <= pa.length; i++) {
            boolean[] next = new boolean[sa.length + 1];
            if (i < pa.length && pa[i] == '*') {
                for(int j = 0; j <= sa.length; j++) {
                    if (match[j] || (j > 0 && next[j - 1] && (pa[i - 1] == '.' || pa[i - 1] == sa[j - 1]))) {
                        next[j] = true;
                    }
                }
                i++;
            } else {
                for(int j = 1; j <= sa.length; j++) {
                    if (match[j - 1] && (pa[i - 1] == '.' || pa[i - 1] == sa[j - 1])) {
                        next[j] = true;
                    }
                }
            }
            match = next;
        }
        return match[sa.length];
    }
}

方法五:动态规划,以s为外层循环。

public class Solution {
    public boolean isMatch(String s, String p) {
        char[] sa = s.toCharArray();
        char[] pa = p.toCharArray();
        boolean[] match = new boolean[pa.length + 1];
        match[0] = true;
        for(int j = 1; j <= pa.length; j++) {
            if (j < pa.length && pa[j] == '*') {
                match[j + 1] = match[j - 1];
                j++;
            }
        }
        for(int i = 1; i <= sa.length; i++) {
            boolean[] next = new boolean[pa.length + 1];
            for(int j = 1; j <= pa.length; j++) {
                if (j < pa.length && pa[j] == '*') {
                    if (next[j -1]) {
                        next[j + 1] = true;
                    }
                    if (match[j + 1] && (pa[j - 1] == '.' || pa[j - 1] == sa[i - 1])) {
                        next[j + 1] = true;
                    }
                    j++;
                } 
                else {
                    if (match[j - 1] && (pa[j - 1] == '.' || pa[j - 1] == sa[i - 1])) {
                        next[j] = true;
                    }
                }
            }
            match = next;
        }
        return match[pa.length];
    }
}

你可能感兴趣的:(文法,匹配,正则表达式,状态机,有限状态自动机,自动机,动态规划,广度优先搜索,困难)