public boolean match(String str) {
        nfa.reset();
        for (char ch : str.toCharArray()) {
            nfa.moveStates(ch);
            // for $ at end of pattern
            if (!nfa.isStrictEnd()) {
                if (nfa.inAcceptState()) {
                    return true;
                }
            }
        }

        if (nfa.inAcceptState()) {
            return true;
        }

        // for ^ at start of pattern, no more change to match again
        if (nfa.isStrictStart()) {
            return false;
        }
        while (str.length() > 0) {
            str = str.substring(1);
            return match(str);
        }

        return false;

    }