本打算周末完成这次作业,但没想到遇到了hard deadline,刚开始看不懂题意,后来发现算法4书上有个类似的问题,才理解了题意。最后晚上加班,上课加班,还好在11:35也就是课程结束前25分钟完成了这次作业。。。
本次作业学到的知识点:
1、java中两个类对象比较相等用equals,因此String对象也应用equals方法,而非“==”。
2、读取命令行参数用args[i],读取文件中的数据才用StdIn等。
3、String对象的长度用方法length,数组的长度用length()。
4、类似于int在泛型中用Integer类,char在泛型中应用Charactor类。
5、用Arrays.sort方法对数组进行自定义排序,首先数组应为基本类型对应的类,然后要重载compare方法,这里参考别人的代码使用了匿名内部类,详见CircularSuffixArray类中构造函数。而对基本类型的数组排序,函数参数为数组名即可(见BurrowsWheeler类44行)。
作业中难以理解的一些地方:
1、后缀数组排序是指将每一行中的后缀字符数组看做字符串进行排序。
2、不需要讲后缀数组存储起来,因为如果字符数组在第n行,那么数组就以输入字符串中的第n个字符开始,从而根据输入字符串就可确定此字符数组。
3、BurrowsWheeler类的逆变换中,通过t数组构造一个<字符,字符在t数组中的下标的队列>的符号表,就可以方便的求出next数组。
1 import java.util.List; 2 import java.util.ArrayList; 3 import edu.princeton.cs.algs4.BinaryStdIn; 4 import edu.princeton.cs.algs4.BinaryStdOut; 5 6 public class MoveToFront { 7 // apply move-to-front encoding, reading from standard input and writing to standard output 8 public static void encode() 9 { 10 List<Character> list = new ArrayList<Character>(); 11 for (int i = 0; i < 256; i++) 12 list.add((char)i); 13 while (!BinaryStdIn.isEmpty()) 14 { 15 char c = BinaryStdIn.readChar(); 16 int index = list.indexOf(c); 17 BinaryStdOut.write(index, 8); 18 list.remove(index); 19 list.add(0, c); 20 } 21 BinaryStdOut.close(); 22 } 23 24 // apply move-to-front decoding, reading from standard input and writing to standard output 25 public static void decode() 26 { 27 List<Character> list = new ArrayList<Character>(); 28 for (int i = 0; i < 256; i++) 29 list.add((char)i); 30 while (!BinaryStdIn.isEmpty()) 31 { 32 int index = BinaryStdIn.readChar(); 33 char c = list.get(index); 34 BinaryStdOut.write(c); 35 list.remove(index); 36 list.add(0, c); 37 } 38 BinaryStdOut.close(); 39 } 40 41 // if args[0] is '-', apply move-to-front encoding 42 // if args[0] is '+', apply move-to-front decoding 43 public static void main(String[] args) 44 { 45 if (args[0].equals("-")) encode(); 46 if (args[0].equals("+")) decode(); 47 } 48 }
1 import java.util.Arrays; 2 import java.util.Comparator; 3 4 public class CircularSuffixArray { 5 private String input; 6 private Integer index[]; 7 // circular suffix array of s 8 public CircularSuffixArray(String s) 9 { 10 if (s == null) throw new java.lang.IllegalArgumentException(); 11 input = s; 12 index = new Integer[s.length()]; 13 for (int i = 0; i < s.length(); i++) 14 index[i] = i; 15 Arrays.sort(index, new Comparator<Integer>() { 16 public int compare(Integer first, Integer second) 17 { 18 int p = first, q = second; 19 for (int i = 0; i < input.length(); i++) 20 { 21 if (p >= input.length()) p = 0; 22 if (q >= input.length()) q = 0; 23 if (input.charAt(p) > input.charAt(q)) return 1; 24 if (input.charAt(p) < input.charAt(q)) return -1; 25 p++; 26 q++; 27 } 28 return 0; 29 } 30 }); 31 } 32 // length of s 33 public int length() 34 { 35 return index.length; 36 } 37 // returns index of ith sorted suffix 38 public int index(int i) 39 { 40 if (i < 0 || i > input.length() - 1) 41 throw new java.lang.IllegalArgumentException(); 42 return index[i]; 43 } 44 // unit testing (required) 45 public static void main(String[] args) 46 { 47 CircularSuffixArray csa = new CircularSuffixArray("ABRACADABRA!"); 48 for (int i = 0; i < csa.length(); i++) 49 System.out.println(csa.index(i)); 50 } 51 }
1 import edu.princeton.cs.algs4.BinaryStdIn; 2 import edu.princeton.cs.algs4.BinaryStdOut; 3 import java.util.Arrays; 4 import edu.princeton.cs.algs4.Queue; 5 import edu.princeton.cs.algs4.ST; 6 7 public class BurrowsWheeler { 8 // apply Burrows-Wheeler transform, reading from standard input and writing to standard output 9 public static void transform() 10 { 11 String input = BinaryStdIn.readString(); 12 CircularSuffixArray csa = new CircularSuffixArray(input); 13 for (int i = 0; i < csa.length(); i++) 14 if (csa.index(i) == 0) 15 BinaryStdOut.write(i); 16 for (int i = 0; i < csa.length(); i++) 17 { 18 int index = csa.index(i) - 1; 19 if (index < 0) index = csa.length() - 1; 20 char c = input.charAt(index); 21 BinaryStdOut.write(c); 22 } 23 BinaryStdOut.close(); 24 } 25 26 // apply Burrows-Wheeler inverse transform, reading from standard input and writing to standard output 27 public static void inverseTransform() 28 { 29 int first = BinaryStdIn.readInt(); 30 String chars = BinaryStdIn.readString(); 31 char[] t = chars.toCharArray(); 32 chars = null; 33 int i = 0, size = t.length; 34 ST<Character, Queue<Integer>> st = new ST<Character, Queue<Integer>>(); 35 for (i = 0; i < size; i++) 36 { 37 if (st.contains(t[i])) st.get(t[i]).enqueue(i); 38 else { 39 Queue<Integer> q = new Queue<Integer>(); 40 q.enqueue(i); 41 st.put(t[i], q); 42 } 43 } 44 Arrays.sort(t); 45 int next[] = new int[size]; 46 for (i = 0; i < size; i++) 47 next[i] = st.get(t[i]).dequeue(); 48 for (i = 0; i < size; i++) 49 { 50 BinaryStdOut.write(t[first]); 51 first = next[first]; 52 } 53 BinaryStdOut.close(); 54 } 55 56 // if args[0] is '-', apply Burrows-Wheeler transform 57 // if args[0] is '+', apply Burrows-Wheeler inverse transform 58 public static void main(String[] args) 59 { 60 if (args[0].equals("-")) transform(); 61 if (args[0].equals("+")) inverseTransform(); 62 } 63 }