Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.
1 2
'.' Matches any single character. '*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
Note:
s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like . or *.
Example 1:
1 2 3 4 5
Input: s = "aa" p = "a" Output: false Explanation: "a" does not match the entire string "aa".
Example 2:
1 2 3 4 5
Input: s = "aa" p = "a*" Output: true Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:
1 2 3 4 5
Input: s = "ab" p = ".*" Output: true Explanation: ".*" means "zero or more (*) of any character (.)".
Example 4:
1 2 3 4 5
Input: s = "aab" p = "c*a*b" Output: true Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".
Example 5:
1 2 3 4
Input: s = "mississippi" p = "mis*is*p*." Output: false
staticclassState{ publicint id; publicchar c; // state char public State out1; // next state 1 public State out2; // next state 2 (for split state only) publicState(int id, char c){ this.id= id; this.c= c; } @Override publicinthashCode(){ return id*c; } @Override publicbooleanequals(Object o){ return id==((State)o).id && c==((State)o).c; } }
privatebooleannfa(String s, String p){ State match= new State(p.length(), END); Set<State> clist= new HashSet<>(); // current list of states Set<State> nlist= new HashSet<>(); // next list of states State start= buildNfa(p, match); addState(clist, start); for(int i=0; i<s.length() && !clist.isEmpty(); i++){ step(clist, s.charAt(i), nlist); Set<State> temp= clist; clist= nlist; nlist= temp; nlist.clear(); } return hasMatch(clist, match); } privatevoidstep(Set<State> clist, char c, Set<State> nlist){ for(State state:clist) if (state.c==ONE && state.out1!=null) addState(nlist, state.out1); elseif (c==state.c && state.out1!=null) addState(nlist, state.out1); } privatevoidaddState(Set<State> list, State state){ if (state.c==SPLIT){ addState(list, state.out1); addState(list, state.out2); return; } list.add(state); } privatebooleanhasMatch(Set<State> list, State match){ return list.contains(match); } private State buildNfa(String p, State match){ int n= p.length(); State start= null; State prev_state= null, state= null, split= null; for(int i=0; i<p.length(); i++){ char c= p.charAt(i); char next_c= i<n-1 ? p.charAt(i+1) : END; if (next_c==MANY){ split= new State(i+1, SPLIT); // split state character state= new State(i, c); split.out2= state; state.out1= split; if (prev_state!=null) prev_state.out1= split; if (start==null) start= split; prev_state= split; i++; // consume 2 characters }else{ state= new State(i, p.charAt(i)); if (prev_state!=null) prev_state.out1= state; if (start==null) start= state; prev_state= state; } } prev_state.out1= match; return start; } }