最长公共子串长度的实现

求两个字符串的最长公共子串长度
ABCBA 和 B
ABCA 的最长公共子串是 ABC,长度为 3

代码

static int  Lcs(String str1,String str2) {
		if(str1==null&&str2==null) return 0;
		
		char[] char1=str1.toCharArray();
		if(char1.length==0) return 0;
		char[] char2=str2.toCharArray();
		if(char2.length==0) return 0;
		//dp[i][j]表示str1[i-1]和str2[j-1]结尾的最长公共子串长度
		int[][] dp=new int[char1.length+1][char2.length+1];//+1才能让length作为下标dp[length+1-1]
		int max=0;
		for(int i=1;i<=char1.length;i++) {
			for(int j=1;j<=char2.length;j++) {
				if(char1[i-1]!=char2[j-1]) continue;
				
					dp[i][j]=dp[i-1][j-1]+1;
					max=Math.max(dp[i][j],max);
			}
			
		}
		return max;
	}

思路

设 dp(i, j) 是以 str1[i – 1]、str2[j – 1] 结尾的最长公共子串长度
dp(i, 0)、dp(0, j) 初始值均为 0

i ∈ [1, str1.length] ,j ∈ [1, str2.length] 为了保证dp数组i-1或j-1时取到两个字符串的第一个字符str1[0]或str2[0]
最长公共子串长度的实现_第1张图片

str1=ABCBA str2=BABCA
假设现在我们要求dp[1,1]即是求str1[0]A、str2[0]B 结尾的最长公共子串长度,str1[0不等str2[0],于是得到的是0,把0写入数组
假设现在我们要求dp[3,4]即是求str1[2]C、str2[3]C 结尾的最长公共子串长度,str1[2]=str2[3],于是与去找各自前面的一个字符,即dp[2,3],发现dp[2,3]求出来是2,于是得到2+1=3,最长公共子串长度是3。

上面的表格里的数是经过遍历存储在dp数组的里的
如果 str1[i – 1] = str2[j – 1],那么 dp(i, j) = dp(i – 1, j – 1) + 1
如果 str1[i – 1] ≠ str2[j – 1],那么 dp(i, j) = 0
最长公共子串的长度是所有 dp(i, j) 中的最大值 max { dp(i, j) }

一维数组实现

减少空间复杂度

static int  Lcs2(String str1,String str2) {
	if(str1==null&&str2==null) return 0;
	
	char[] char1=str1.toCharArray();
	if(char1.length==0) return 0;
	char[] char2=str2.toCharArray();
	if(char2.length==0) return 0;
	char[] rowchar=char1;
	char[] colchar=char2;
	if(char1.length<char2.length) {
		colchar=char1;
		rowchar=char2;
	}
	int[] dp=new int[colchar.length+1];
	int max=0;
	for(int row=1;row<=rowchar.length;row++) {
		int cur=0;
		for(int col=1;col<=colchar.length;col++) {
			int lefttop=cur;
			cur=dp[col];
			if(char1[row-1]!=char2[col-1]) {
				dp[col]=0;
			}else {
				dp[col]=lefttop+1;
				max=Math.max(dp[col],max);
			}
			
		}
		
	}
	return max;
}

你可能感兴趣的:(最长公共子串长度的实现)