算法导论 习题 15.4.4

15.4.4

1)使用 2*min(m,n)个条目计算LCS长度

实际上,计算特定的 C[i,j]只需用到 C[i-1,j-1] 或者 C[i-1,j] C[i,j-1]。所以交替使用两个大小为min(m,n)的数组表示 当前行 和 上一行 即可。

// Use dynamic programming to calculate LCS length of two strings with a 2*min(m,n) size table 
	public static <T> int findLCSLengthBy2Array(T[] longString,T[] shortString){
		int size = Math.min(longString.length, shortString.length)-1;
		int length = 0;
		if(size>0){
			int[][] lcs = new int[2][size+1];
			for(int i=1;i<longString.length;i++){
				int k=1;
				for(int j=1;j<shortString.length;j++){
					if(longString[i]==shortString[j]){
						lcs[k][j] = lcs[k-1][j-1] +1;
					}else if(lcs[k-1][j] >= lcs[k][j-1]){
						lcs[k][j] = lcs[k-1][j];
					}else{
						lcs[k][j] = lcs[k][j-1];
					}
				}
				// Assign current row to previous row.
				lcs[k-1] = lcs[k].clone();
				// And reset current row.
				for(int m=0;m<lcs[1].length;m++){
					lcs[1][m] = 0;
				}
			}
			// Final result is saved at lcs[previous][min(m,n)]
			length = lcs[0][size];
		}
		return length ;
	}

2) 使用 min(m,n) +O(1) 的条目计算 LCS长度。

设计算到 i 行 j 列,于是 C[i,j-1]为已知,而从 j 到 min(m,n)列未被计算,可以用于表示 C[i-1,j]。于是只剩下 C[ i-1 , j-1],用额外的一个变量或定义多一个数组元素保存。在每次计算 C[i,j]前保存好 C[i-1, j-1]用于C[i,j+1]的计算。

// Use dynamic programming to calculate LCS length of two strings , with a min(m,n)+1 size array 
	public static int findLCSLengthBy1Array(char[] longArray,char[] shortArray){
		int size = Math.min(longArray.length, shortArray.length)-1;
		int length = 0;
		if(size>0){
			int[] lcs = new int[size+1];
			for(int i=1;i<longArray.length;i++){
				int lcs0 = lcs[0];
				for(int j=1;j<shortArray.length;j++){
					// Save lcs[j] acting as C[i-1,j-1] first for the next calculation.
					int swap = lcs[j];
					if(longArray[i]==shortArray[j]){
						// If two chars match, calculate lcs[j] =  current C[i-1,j-1] + 1
						lcs[j] = lcs[0]+1;
					}else if(lcs[j] >=lcs[j-1]){
						lcs[j] = lcs[j];
					}else{
						lcs[j] = lcs[j-1];
					}
					// Get C[i,j] after it is modified.
					lcs[0] = swap;
				} 
				lcs[0] = lcs0;
			}
			length = lcs[size];
		}
		return length ;
	}


=========== 与一般的计算LCS表的方法作对比 进行测试==============

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];
		dp_bottomUp_findLCSLength(x1,y1,bottom_lcsLength1);
		
		// Test that findLCSLengthBy2Array() and findLCSLengthBy1Array() are correct.
		System.out.println("The LCS length calculated by normal m*n table is " + bottom_lcs.length());
		System.out.println("The LCS length calculated by 2*min(m,n) entries is "+ findLCSLengthBy2Array(x1, y1));
		System.out.println("The LCS length calculated by min(m,n)+1 entries is "+findLCSLengthBy1Array(x1, y1));
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值