Dynamic Programming (II)
1. The Longest Prefix
This is my solution to USACO training problem "prefix":
1 import java.io.*; 2 import java.util.*; 3 4 public class prefix { 5 public static Scanner input; 6 public static PrintWriter output; 7 public static String [] dict; 8 public static char [] obj; 9 10 private static int solve(int num,int len) { 11 int [] dp = new int [len+1]; 12 // dp[i] will be the length of the longest prefix 13 // that starts from obj[i] 14 for (int i=len-1;i>=0;i--) { 15 for (int j=0;j<num;j++) { 16 if (!consult(i,j,len)) { 17 continue; 18 } 19 int d = dict[j].length(); 20 if (d+dp[i+d]>dp[i]) { 21 dp[i] = dp[i+d]+d; 22 } 23 } 24 } 25 return dp[0]; 26 } 27 private static boolean consult(int pos,int j,int len) { 28 // Returns whether obj[pos] starts with dict[j] 29 for (int i=0;i<dict[j].length();i++) { 30 if (pos+i>=len||obj[pos+i]!=dict[j].charAt(i)) { 31 return false; 32 } 33 } 34 return true; 35 } 36 public static void main(String[] args) throws IOException{ 37 dict = new String [256]; 38 obj = new char [200000]; 39 input = new Scanner(new FileReader("prefix.in")); 40 int num = 0; 41 do { 42 dict[num++] = input.next(); 43 } while (!dict[num-1].equals(".")); 44 String line = null; 45 int len = 0; 46 while (input.hasNext()) { 47 line = input.nextLine(); 48 for (int i=0;i<line.length();i++) { 49 obj[len++] = line.charAt(i); 50 } 51 } 52 input.close(); 53 output = new PrintWriter(new FileWriter("prefix.out")); 54 output.println(solve(num,len)); 55 output.close(); 56 } 57 }
2. Stringsobits
This is my solution to USACO training problem "kimbits":
1 import java.io.*; 2 import java.util.*; 3 4 public class kimbits { 5 public static Scanner input; 6 public static PrintWriter output; 7 public static long [][] dp; 8 9 private static void binSrch(int len,int num,long idx) { 10 // Generate the desired string from left to right by 11 // using a Divide-and-Conquer method 12 if (len<=0) { 13 output.println(); 14 } else if (idx<=dp[len-1][num]) { 15 output.print(0); 16 binSrch(len-1,num,idx); 17 } else { 18 output.print(1); 19 binSrch(len-1,num-1,idx-dp[len-1][num]); 20 } 21 } 22 public static void main(String[] args) throws IOException{ 23 // Obtain the input: 24 input = new Scanner(new FileReader("kimbits.in")); 25 int len = input.nextInt(); 26 int num = input.nextInt(); 27 long idx = input.nextLong(); 28 input.close(); 29 // Dynamic Programming: 30 // dp[i][j] will be the number of strings of length i, 31 // which have j or fewer 1s 32 dp = new long [len+1][num+1]; 33 for (int j=0;j<=num;j++) { 34 // please pay attention to this basis 35 dp[0][j] = 1; 36 } 37 for (int i=1;i<=len;i++) { 38 dp[i][0] = 1; 39 for (int j=1;j<=num;j++) { 40 dp[i][j] = dp[i-1][j]+dp[i-1][j-1]; 41 } 42 } 43 // Phrase the output: 44 output = new PrintWriter(new FileWriter("kimbits.out")); 45 binSrch(len,num,idx); 46 output.close(); 47 } 48 }
3. Contact
This is my solution to USACO training problem "contact":
1 import java.io.*; 2 import java.util.*; 3 4 public class contact { 5 public static Scanner input; 6 public static PrintWriter output; 7 public static int [] info; 8 public static int [] dp; 9 10 private static class Subseq { 11 public int code, freq; 12 13 public Subseq(int code, int freq) { 14 this.code = code; 15 this.freq = freq; 16 } 17 public String toString() { 18 return seqHelp(code); 19 } 20 private String seqHelp(int val) { 21 // Decode the code of the 0-1 sequence 22 if (val==0) { 23 return ""; 24 } else { 25 String str = String.valueOf(1-(val&1)); 26 // turn to the parent node recursively 27 return seqHelp((val-1)>>1)+str; 28 } 29 } 30 } 31 32 private static void solve(int min,int max,int num,int len) { 33 PriorityQueue<Subseq> q = new PriorityQueue<Subseq>(1<<13, 34 new Comparator<Subseq> () { 35 public int compare(Subseq s1,Subseq s2) { 36 // ATTENTION: there is an order on code when freq ties 37 if (s1.freq>s2.freq) { 38 return -1; 39 } else if (s1.freq<s2.freq){ 40 return 1; 41 } else if (s1.code<s2.code) { 42 return -1; 43 } else if (s1.code>s2.code) { 44 return 1; 45 } else { 46 return 0; 47 } 48 } 49 } 50 ); 51 // Dynamic Programming: 52 // each sequence is coded into an integer, 53 // which is an index of a complete binary tree 54 dp = new int[1<<13]; 55 for (int i=0;i<len;i++) { 56 int code = 0; 57 for (int j=0;j<max&&i+j<len;j++) { 58 if (info[i+j]==0) { 59 code = (code<<1)+1; 60 } else { 61 code = (code<<1)+2; 62 } 63 dp[code]++; 64 } 65 } 66 for (int i=(1<<min)-1;i<(1<<max<<1);i++) { 67 if (dp[i]>0) { 68 // ATTENTION: do not enqueue a 0-1 sequence 69 // unless its frequency is greater than 0 70 q.add(new Subseq(i,dp[i])); 71 } 72 } 73 // This is the most frustrating part: 74 // phrase the output in the format required 75 int tmp = 0; 76 for (int i=0;i<num;i++) { 77 if (q.isEmpty()) { 78 break; 79 } else { 80 tmp = q.peek().freq; 81 output.println(tmp); 82 } 83 int mod = 0; 84 while (!q.isEmpty()&&q.peek().freq==tmp) { 85 if (mod>0) { 86 output.print(" "); 87 } 88 output.print(q.poll()); 89 if (mod==5) { 90 output.println(); 91 } 92 mod = (mod+1)%6; 93 } 94 if (mod>0) { 95 output.println(); 96 } 97 } 98 } 99 public static void main(String[] args) throws IOException { 100 info = new int [200000]; 101 // Obtain the input: 102 input = new Scanner(new FileReader("contact.in")); 103 int min = input.nextInt(); 104 int max = input.nextInt(); 105 int num = input.nextInt(); 106 String line; 107 int len = 0; 108 while (input.hasNext()) { 109 line = input.nextLine(); 110 for (int i=0;i<line.length();i++) { 111 info[len++] = line.charAt(i)-'0'; 112 } 113 } 114 input.close(); 115 max = (max<len)? max:len; 116 // Phrase the output: 117 output = new PrintWriter(new FileWriter("contact.out")); 118 solve(min,max,num,len); 119 output.close(); 120 } 121 }