Description
Consider a binary string (b1…bN) with N binary digits. Given such a string, the matrix of Figure 1 is formed from the rotated versions of the string.
| b1 | b2 | … | bN-1 | bN |
| b2 | b3 | … | bN | b1 |
| … | ||||
| bN-1 | bN | … | bN-3 | bN-2 |
| bN | b1 | … | bN-2 | bN-1 |
Figure 1. The rotated matrix
Then rows of the matrix are sorted in alphabetical order, where ‘0’ is before ‘1’. You are to write a program which, given the last column of the sorted matrix, finds the first row of the sorted matrix.
As an example, consider the string (00110). The sorted matrix is
| 0 | 0 | 0 | 1 | 1 |
| 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 1 | 0 | 0 |
| 1 | 0 | 0 | 0 | 1 |
| 1 | 1 | 0 | 0 | 0 |
and the corresponding last column is (1 0 0 1 0). Given this last column your program should determine the first row, which is (0 0 0 1 1).
Input
The first line contains one integer N <= 3000, the number of binary digits in the binary string. The second line contains N integers, the binary digits in the last column from top to bottom.
Output
The first line contains N integers: the binary digits in the first row from left to right.
Sample Input
5 1 0 0 1 0
Sample Output
0 0 0 1 1
Solution below . . .
Solution
/*
* The process of forming a matrix from rotated versions of a string,
* sorting the rows, and taking the value from the right-hand column
* is called a Burrows-Wheeler Transform, and is part of the
* Burrows-Wheeler Data Compression Algorithm.
*
* This link has a discussion of the algorithm, as well as how to
* invert the transform back to the sorted matrix:
*
* http://www.cs.princeton.edu/courses/archive/fall07/cos226/assignments/burrows.html
*/
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
static void invert(int bwtArr[]) {
int i;
int len = bwtArr.length;
int[] lShift = new int[len];
int[] sortedBwt = bwtArr.clone();
// Index at which original string appears
// in the sorted rotations list
int x = 0;
Arrays.sort(sortedBwt);
@SuppressWarnings("unchecked")
LinkedList<Integer>[] arr = new LinkedList[2];
for (int j = 0; j < arr.length; j++) {
arr[j] = new LinkedList<Integer>();
}
for (i = 0; i < len; i++) {
arr[bwtArr[i]].addLast(i);
}
for (i = 0; i < len; i++) {
computeLShift(arr, sortedBwt, i, lShift);
}
// Decodes the BWT
for (i = 0; i < len; i++) {
x = lShift[x];
System.out.print(bwtArr[x] + " ");
}
}
static void computeLShift(LinkedList<Integer>[] arr, int[] sortedBwt, int index,
int[] lShift)
{
LinkedList<Integer> head = arr[sortedBwt[index]];
lShift[index] = head.getFirst();
head.removeFirst();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] bwtArr = new int[N];
for (int i = 0; i < N; i++) {
bwtArr[i] = sc.nextInt();
}
sc.close();
invert(bwtArr);
}
}