From https://leetcode.com/problems/regular-expression-matching/#/description
Ref: Algorithms and Data Structures II Course - Princeton
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
Solution with state machine.
Runtime O(nm) where n=len(s), m=len(p)
Solution in C++
//
// Created by Sasinda Premarathna on 4/22/17.
//
#include <string>
#include <list>
#include <iostream>
#include <set>
using namespace std;
class Regex {
public:
bool isMatch(string s, string p) {
set<int> currStates;
list<int> midxes;
bool stop_state;
updateCurrentStates(currStates, p, -1);
for(int i=0; i<s.length(); i++ ){
matches(currStates, p, s[i],midxes );
if(midxes.size()==0){
return false;
}
currStates.clear();
for(int m :midxes){
updateCurrentStates(currStates, p, m);
}
midxes.clear();
}
return currStates.find(p.length())!=currStates.end();
}
private:
/**
* return true if final stop state is also reached
* @param matchStates
* @param p
* @param index
* @return
*/
void updateCurrentStates(set<int> &matchStates, string &p, int index){
bool stop_state= false;
int i=index+1;
for( ; i <= p.length(); i++) {
if(i<p.length() && p[i]=='*'){
i--;
//if i<0 throw exception invalid pattern. and ** case as well.
}
matchStates.insert(i);
if(i+1< p.length() && p[i+1]!='*'){
break;
} else{
i++;
}
}
//debug print
cout<< "matched state:";
for (int n : matchStates) {
std::cout << ","<< n;
}
cout << "\n";
}
/**
* return the next state in the state machine. -1 if this does not match to current state.
* @param matchStates
* @param p
* @param c
* @return
*/
void matches(set<int> &matchStates, string &p, char c, list<int> &result){
for(int i:matchStates) {
if(i>=p.length())continue;
if (c == p[i] || p[i] == '.') {
result.push_back(i);
}
}
}
};
int main(){
Regex s;
// printf("%i\n", s.isMatch("a", "ab*"));
// printf("%i\n", s.isMatch("a", "ab*b*"));
// printf("%i\n", s.isMatch("", "a*b*b*"));
// printf("%i\n", s.isMatch("", ".*"));
// printf("%i\n", s.isMatch("", "."));
// printf("%i\n", s.isMatch("aab", "c*a*b"));
// printf("%i\n", s.isMatch("aab", ".*"));
// printf("%i\n", s.isMatch("aab", "..*"));
// printf("%i\n", s.isMatch("aabb", ".*b"));
printf("%i\n", s.isMatch("aabc", ".*bc"));
// printf("%i\n", s.isMatch("aa", "a"));
}