问题:有两个字符串str1和str2,求出两个字符串中最长公共子串长度。
比如:str1="acbcbcef",str2="abcbced",则str和str2的最长公共子串为bcbce,最长公共子串长度为5。
算法思路:
1、把两个字符串分别以行和列组成一个二维矩阵。record[i][j]
2、比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0。
3、通过查找出值为1的最长对角线就能找到最长公共子串。
针对于上面的两个字符串我们可以得到的二维矩阵如下:
从上图可以看到,str1和str2共有5个公共子串,但最长的公共子串长度为5。
为了优化算法,在计算某个二维矩阵的值的时候,顺便得出当前最长的公共子串的长度,即某个二维矩阵元素的值
由record[i][j]=1演变为record[i][j]=1 +record[i-1][j-1],
这样就避免了后续查找对角线长度的操作了。
修改后的二维矩阵如下:
String getLCS(String str1, String str2) { if(str1==NULL||str2==NULL){ return NULL; } int len1 = str1.length(); int len2 = str2.length(); int[][] dp = new int[len1][len2]//str1的len1元素和str2的len2元素是否相等。 int maxLen = 0, endIndex = 0; for(int i=0; i<len1; i++){ for (int j = 0; j <len2; j++) {
if (str1.charAt(i)==str2.charAt(j)) { if (i==0 || j==0){//相同了,第1行或列的为1,因为record[i-1][j-1],会出现负下标。 record[i][j] = 1; }else{ record[i][j] = record[i-1][j-1] + 1; } }else{ record[i][j] = 0; } if (record[i][j] > maxLen) { maxLen = record[i][j]; endIndex = i; //记录i,则从str1中提取子串 } } } return str1.substring(endIndex-maxLen+1,endIndex+1);//[) }