private boolean isScrambleCore(String s1, String s2) {
        boolean result = false;
        List<String> key = new ArrayList<String>();
        key.add( s1 );
        key.add( s2 );
        if( cache.containsKey( key ) ) return cache.get( key );

        if( s1.equals(s2) ) {
            cache.put( key, true );
            return true;
        }

        if( s1.length() == 1 ) {
            cache.put( key, false );
            return false;
        }

        int n = s1.length();

        for( int i = 0; i < n - 1; i++ ) {
            // forward
            String s11 = s1.substring(0, i+1);
            String s12 = s1.substring(i+1);
            String s21 = s2.substring(0, i+1);
            String s22 = s2.substring( i + 1 );

            if( isScrambleCore(s11, s21 ) && isScrambleCore( s12, s22 ) ) {
                result = true;
                break;
            }

            // backward
            s21 = s2.substring(0, n - 1 - i );
            s22 = s2.substring(n - 1 - i );

            if( isScrambleCore(s11, s22 ) && isScrambleCore( s12, s21 ) ) {
                result = true;
                break;
            }
        }
        cache.put( key, result );
        return result;
    }