The whole question is Simplified regular expression engine. I have solved the question, and in turn felt the need to get it reviewed. Any suggestions for clean up and optimization would help. Also please verify my complexity: Complexity: O (n), where n is the length of the longer or regex or string.
public final class Regex {
private static final char STAR = '*';
private static final char DOT = '.';
private Regex() {};
/**
* The index of first non-star character following first occurence of star
* eg: if regex is a**b, then index is startIndex is 1 and return value is 3 (index of b)
*
* @param regex : the regex string.
* @param starIndex : index of the first occurene of * after a non *, eg: a**b, then starIndex would be 1
* @return : the index of first non-star character following first occurence of star
*/
private static int getNonStarIndex(String regex, int starIndex) {
assert regex != null;
assert starIndex >= 0 && starIndex < regex.length();
for (int k = starIndex + 1; k < regex.length(); k++) {
if (regex.charAt(k) != '*') {
return k;
}
}
return regex.length();
}
/**
* A * means 0 or more number of any char matches
* A . means just a single any char match.
*
* @param regex : The regex to match the string again
* @param str : The string to be matched.
* @return : true / false
*/
public static boolean match(String regex, String str) {
if (regex == null) throw new NullPointerException("The regex cannot be null");
if (str == null) throw new NullPointerException("The str cannot be null");
int i = 0;
int j = 0;
while ((i < regex.length() && j < str.length())) {
if (regex.charAt(i) == str.charAt(j) || regex.charAt(i) == DOT) {
i++; j++;
} else if (regex.charAt(i) == STAR) {
int nextNonStarIndex = getNonStarIndex(regex, i);
/*
* For a case where regex and string, both have not yet reached the last char but regex is all *'s till end.
* Eg: Regext abc*** && String is abcxyz
*/
if (nextNonStarIndex == regex.length()) return true;
/*
* regex: a*.*c, abc
*/
if (regex.charAt(nextNonStarIndex) == DOT) {i = nextNonStarIndex + 1; j++; continue;}
boolean match = false;
for (int k = j; k < str.length(); k++) {
if (regex.charAt(nextNonStarIndex) == str.charAt(k)) {
// now move to the next char, after a match succeeds with first char after adjacent stars.
i = nextNonStarIndex + 1;
j = k + 1;
match = true;
break;
}
}
if (!match) {
return false;
}
} else {
return false;
}
}
/*
* String has reached the end but not the regex.
* regx = "abc**" and str = "abc";
*/
if (i != regex.length()) {
for (int x = i; x < regex.length() ; x++) {
if (regex.charAt(x) != STAR) return false;
}
}
if (j != str.length()) {
return false;
}
return true;
}
public static void main(String[] args) {
String[] regexList = { "abc****", "abc", "a*b*c", "****abc", "**a**b**c****", "abc*"};
String str1 = "abc";
for (String regex : regexList) {
System.out.println(Regex.match(regex, str1));
}
String regex = "abc****";
String[] strList1 = {"abcxyz", "abcx", "abc"};
for (String str : strList1) {
System.out.println(Regex.match(regex, str));
}
regex = "***abc";
String[] strList2 = {"xyzabc", "xabc", "abc"};
for (String str : strList2) {
System.out.println(Regex.match(regex, str));
}
System.out.println(Regex.match("a.c", "abc"));
System.out.println(Regex.match("a*.*c", "abc"));
}
}
System.out.println(Regex.match("", ""));
\$\endgroup\$