private static int editDistanceTranspose(CharSequence cSeq1,
                                             CharSequence cSeq2) {

        // cSeq1.length >= cSeq2.length > 1
        int xsLength = cSeq1.length() + 1; // > ysLength
        int ysLength = cSeq2.length() + 1; // > 2

        int[] twoLastSlice = new int[ysLength];
        int[] lastSlice = new int[ysLength];
        int[] currentSlice = new int[ysLength];

        // x=0: first slice is just inserts
        for (int y = 0; y < ysLength; ++y)
            lastSlice[y] = y;  // y inserts down first column of lattice

        // x=1:second slice no transpose
        currentSlice[0] = 1; // insert x[0]
        char cX = cSeq1.charAt(0);
        for (int y = 1; y < ysLength; ++y) {
            int yMinus1 = y-1;
            currentSlice[y] = Math.min(cX == cSeq2.charAt(yMinus1)
                                       ? lastSlice[yMinus1] // match
                                       : 1 + lastSlice[yMinus1], // subst
                                       1 + Math.min(lastSlice[y], // delelte
                                                    currentSlice[yMinus1])); // insert
        }

        char cYZero = cSeq2.charAt(0);
    
        // x>1:transpose after first element
        for (int x = 2; x < xsLength; ++x) {
            char cXMinus1 = cX;
            cX = cSeq1.charAt(x-1);

            // rotate slices
            int[] tmpSlice = twoLastSlice;
            twoLastSlice = lastSlice;
            lastSlice = currentSlice;
            currentSlice = tmpSlice;

            currentSlice[0] = x; // x deletes across first row of lattice

            // y=1: no transpose here
            currentSlice[1] = Math.min(cX == cYZero
                                       ? lastSlice[0] // match
                                       : 1 + lastSlice[0], // subst
                                       1 + Math.min(lastSlice[1], // delelte
                                                    currentSlice[0])); // insert

            // y > 1: transpose
            char cY = cYZero;
            for (int y = 2; y < ysLength; ++y) {
                int yMinus1 = y-1;
                char cYMinus1 = cY;
                cY = cSeq2.charAt(yMinus1);
                currentSlice[y] = Math.min(cX == cY
                                           ? lastSlice[yMinus1] // match
                                           : 1 + lastSlice[yMinus1], // subst
                                           1 + Math.min(lastSlice[y], // delelte
                                                        currentSlice[yMinus1])); // insert
                if (cX == cYMinus1 && cY == cXMinus1)
                    currentSlice[y] = Math.min(currentSlice[y],1+twoLastSlice[y-2]);
            }
        }
        return currentSlice[currentSlice.length-1];
    }