private static Cell construct(Sequence s1, Sequence s2, float[][] matrix,
            float o, float e, byte[] pointers, short[] sizesOfVerticalGaps,
            short[] sizesOfHorizontalGaps) {
        long start = System.currentTimeMillis();

        char[] a1 = s1.toArray();
        char[] a2 = s2.toArray();

        int m = s1.length() + 1;
        int n = s2.length() + 1;

        float f; // score of alignment x1...xi to y1...yi if xi aligns to yi
        float[] g = new float[n]; // score if xi aligns to a gap after yi
        float h; // score if yi aligns to a gap after xi
        float[] v = new float[n]; // best score of alignment x1...xi to
        // y1...yi
        float vDiagonal;

        g[0] = Float.NEGATIVE_INFINITY;
        h = Float.NEGATIVE_INFINITY;
        v[0] = 0;

        for (int j = 1; j < n; j++) {
            g[j] = Float.NEGATIVE_INFINITY;
            v[j] = 0;
        }

        float similarityScore, g1, g2, h1, h2;

        Cell cell = new Cell();

        for (int i = 1, k = n; i < m; i++, k += n) {
            h = Float.NEGATIVE_INFINITY;
            vDiagonal = v[0];
            for (int j = 1, l = k + 1; j < n; j++, l++) {
                similarityScore = matrix[a1[i - 1]][a2[j - 1]];

                // Fill the matrices
                f = vDiagonal + similarityScore;

                g1 = g[j] - e;
                g2 = v[j] - o;
                if (g1 > g2) {
                    g[j] = g1;
                    sizesOfVerticalGaps[l] = (short) (sizesOfVerticalGaps[l - n] + 1);
                } else {
                    g[j] = g2;
                }

                h1 = h - e;
                h2 = v[j - 1] - o;
                if (h1 > h2) {
                    h = h1;
                    sizesOfHorizontalGaps[l] = (short) (sizesOfHorizontalGaps[l - 1] + 1);
                } else {
                    h = h2;
                }

                vDiagonal = v[j];
                v[j] = maximum(f, g[j], h, 0);

                // Determine the traceback direction
                if (v[j] == 0) {
                    pointers[l] = Directions.STOP;
                } else if (v[j] == f) {
                    pointers[l] = Directions.DIAGONAL;
                } else if (v[j] == g[j]) {
                    pointers[l] = Directions.UP;
                } else {
                    pointers[l] = Directions.LEFT;
                }

                // Set the traceback start at the current cell i, j and score
                if (v[j] > cell.getScore()) {
                    cell.set(i, j, v[j]);
                }
            }
        }
        return cell;
    }