动态规划-最长公共子串

来源:互联网 发布:键盘照片是什么软件 编辑:程序博客网 时间:2024/06/07 07:45

动态规划:动态规划是一种思想。是由暴力递归简化而来的编程思想,在编程中变化很大。我的总结如下:

两个字符串的最长公共子串,首先公共子串和子序列不同的是子串必须连续。那么dp[i][j]的表示含义会有所不同。

第一步:dp[i][j]表示以str[i]和str[j]为结尾的最长公共子串。体会一下,不同在于子序列dp[i][j]我们说的是个区间,i和j是否匹配我们没定。而此时dp[i][j]我们规定了i和j必须匹配,不匹配则为0。

第二步:若str1[i]==str2[j],则dp[i][j]=dp[i-1][j-1];

                若str1[i]!=str2[i],则dp[i][j]=0

这样解释之后,我们知道最长公共子串若匹配,在dp二维表中是斜线,那么可以用对应关系搞成程序,而没生成dp表。

代码如下:

public static String lcst1(String str1, String str2) {if (str1 == null || str2 == null || str1.equals("") || str2.equals("")) {return "";}char[] chs1 = str1.toCharArray();char[] chs2 = str2.toCharArray();int[][] dp = getdp(chs1, chs2);int end = 0;int max = 0;for (int i = 0; i < chs1.length; i++) {for (int j = 0; j < chs2.length; j++) {if (dp[i][j] > max) {end = i;max = dp[i][j];}}}return str1.substring(end - max + 1, end + 1);}

第一种方法获得dp:

public static int[][] getdp(char[] str1, char[] str2) {int[][] dp = new int[str1.length][str2.length];for (int i = 0; i < str1.length; i++) {if (str1[i] == str2[0]) {dp[i][0] = 1;}}for (int j = 1; j < str2.length; j++) {if (str1[0] == str2[j]) {dp[0][j] = 1;}}for (int i = 1; i < str1.length; i++) {for (int j = 1; j < str2.length; j++) {if (str1[i] == str2[j]) {dp[i][j] = dp[i - 1][j - 1] + 1;}}}return dp;}

第二种方法获取dp:

public static String lcst2(String str1, String str2) {if (str1 == null || str2 == null || str1.equals("") || str2.equals("")) {return "";}char[] chs1 = str1.toCharArray();char[] chs2 = str2.toCharArray();int row = 0; // 斜线开始位置的行int col = chs2.length - 1; // 斜线开始位置的列int max = 0; // 记录最大长度int end = 0; // 最大长度更新时,记录子串的结尾位置while (row < chs1.length) {int i = row;  int j = col;int len = 0;// 从(i,j)开始向右下方遍历。ij是起点while (i < chs1.length && j < chs2.length) {if (chs1[i] != chs2[j]) {len = 0;} else {len++;}// 记录最大值,以及结束字符的位置if (len > max) {end = i;max = len;}i++;j++;}if (col > 0) { // 斜线开始位置的列先向左移动col--;} else { // 列移动到最左之后,行向下移动row++;}}return str1.substring(end - max + 1, end + 1);}public static void main(String[] args) {String str1 = "ABC1234567DEFG";String str2 = "HIJKL1234567MNOP";System.out.println(lcst1(str1, str2));System.out.println(lcst2(str1, str2));}



0 0