private boolean match(String str1, int s1, int e1, String str2, int s2, int e2) {
        List<Integer> key = new ArrayList<>(4);
        key.add(s1);
        key.add(e1);
        key.add(s2);
        key.add(e2);
        Boolean result = cache.get(key);
        if (result != null)
            return result;
        result = true;
        for (int i = 0; i < e1 - s1; i++) {
            if (str1.charAt(s1 + i) != str2.charAt(s2 + i)) {
                result = false;
                break;
            }
        }
        if (!result) {
            for (int len = 1; len < e1 - s1; len++) {
                int d1 = s1 + len, d2 = s2 + len;
                if (match(str1, s1, d1, str2, s2, d2) &&
                    match(str1, d1, e1, str2, d2, e2)) {
                    result = true;
                    break;
                }
                d2 = e2 - len;
                if (match(str1, s1, d1, str2, d2, e2) &&
                    match(str1, d1, e1, str2, s2, d2)) {
                    result = true;
                    break;
                }
            }
        }
        cache.put(key, result);
        return result;
    }