算法导论 习题 15.4.3

15.4.3

自顶向下的DP,按照标准的memoized递归写法即可。代码如下:

public static <T> void dp_topDown_findLCSLength(T[] x,T[] y,int[][] lcsLength){
		for(int i=0;i<y.length;i++){
			lcsLength[0][i] =0;
		}
		for(int i=0;i<x.length;i++){
			lcsLength[i][0] =0;
		}
		// Initialize the auxiliary table
		for(int i=1;i<x.length;i++){
			for(int j=1;j<y.length;j++){
				lcsLength[i][j] = -1;
			}
		}
		// Call the memoized-type recursive function that actually performs the task.
		memoized_findLCSLength(x, y, lcsLength, x.length-1, y.length-1);
	}
	
	private static <T> int memoized_findLCSLength(T[] x,T[] y,int[][] lcsLength,int i,int j){
		if(lcsLength[i][j]>=0){
			// Keep track of how many recursion calls are saved.
			savedRecursions++;
			return lcsLength[i][j];
		}else{
			int result = 0; 
			if(x[i] == y[j])
				result = memoized_findLCSLength(x, y, lcsLength, i-1, j-1) + 1;
			else{
				result = Math.max(memoized_findLCSLength(x, y, lcsLength, i-1, j),
							 memoized_findLCSLength(x, y, lcsLength, i, j-1));
			}
			// Do not forget to update auxiliary table.
			lcsLength[i][j] = result;
			return result;
		}

此外,定义一个自底向下的DP算法,用于测试两种方法的结果是否一致:

public static <T> void dp_bottomUp_findLCSLength(T[] x,T[] y,int[][] lcsLength){
		for(int i=0;i<y.length;i++){
			lcsLength[0][i] =0;
		}
		for(int i=0;i<x.length;i++){
			lcsLength[i][0] =0;
		}
		for(int i=1;i<x.length;i++){
			for(int j=1;j<y.length;j++){
				if(x[i] == y[j]){
					lcsLength[i][j] = lcsLength[i-1][j-1] + 1;
				}else if(lcsLength[i-1][j] >= lcsLength[i][j-1]){
					lcsLength[i][j] = lcsLength[i-1][j];
				}else{
					lcsLength[i][j] = lcsLength[i][j-1];
				}
			}
		}
	}


findLCS用于查找一个具体的最优解:

// Get a concrete optimal solution.
	public static <T> String findLCS(int[][] lcsLength,T[] x,T[] y){
		StringBuilder sb = new StringBuilder();
		int i=x.length-1;
		int j=y.length-1;
		while(i>0 && j>0){
			if(x[i] == y[j]){
				sb.insert(0, x[i]);
				i = i-1;
				j = j-1;
			}else if(lcsLength[i-1][j] >= lcsLength[i][j-1]){
				i = i -1;
			}else{
				j = j-1;
			}
		}
		return sb.toString();
	}

=======测试==========

public static void main(String[] args) {
		
		Character[] x1 = new Character[201];
		Character[] y1 = new Character[101];
		x1[0] = '?';
		y1[0] = '?';
		
		// Randomly generate character of English letters in lower case.
		for(int i=1;i<x1.length;i++){
			char randomChar = (char)(97+(int)(Math.random()*26));
			x1[i] = randomChar;
		}
		for(int i=1;i<y1.length;i++){
			char randomChar = (char)(97+(int)(Math.random()*26));
			y1[i] = randomChar;			
		}
		
		int[][] bottom_lcsLength1 = new int[x1.length][y1.length];
		int[][] top_lcsLength1 = new int[x1.length][y1.length];
		
		
		dp_topDown_findLCSLength(x1, y1, top_lcsLength1);
		dp_bottomUp_findLCSLength(x1,y1,bottom_lcsLength1);
		
		String bottom_lcs = findLCS(bottom_lcsLength1,x1, y1);
		String top_lcs = findLCS(top_lcsLength1, x1, y1);
		
		
		// Test that bottom-up and top-down approaches get the same result.
		System.out.println("The longest common sequence found by bottom-up manner is " + bottom_lcs);
		System.out.println("The longest common sequence found by top-down manner is " + top_lcs);
		System.out.println("Are they the same? " + bottom_lcs.equals(top_lcs));}


你可能感兴趣的:(算法导论 习题 15.4.3)