【数据结构与算法】最长公共子串 最长公共子序列

来源:互联网 发布:java web 前后端分离 编辑:程序博客网 时间:2024/05/16 03:16

1.最长公共子串:找出s和t的公共子字符串的最大长度。

使用dp,定义子问题dp[i][j]:公共子串结束在位置i,j的长度。如果s[i] != t[j],那么很显然是0,否则dp[i][j] = dp[i - 1][j - 1] + 1。

代码:

public int longestCommonSubString(String s, String t){int[][] dp = new int[s.length()][t.length()];int max = 0;for(int i = 0; i < s.length(); i++){for(int j = 0; j < t.length(); j++){if(s.charAt(i) == t.charAt(j))dp[i][j] = 1 + ((i - 1 < 0 || j - 1 < 0)?0:dp[i - 1][j - 1]);else dp[i][j] = 0;max = Math.max(dp[i][j], max);}}return max;}

2.最长公共子序列:找出s和t的公共子序列的最大长度,子序列不需要连续。

使用dp,定义子问题dp[i][j]:s[0-i]和t[0-j]的最长公共子序列长度。那么首先可以利用之前的结论,即dp[i][j] = max(dp[i - 1][j] + dp[i][j - 1])无论什么情况,dp[i][j]都等于这个。这是由于子序列的性质,大的范围成立,小的范围当然也成立。然后看如果s[i]=t[j],那么还可以用dp[i - 1][j - 1] +1 来尝试,dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1)。

代码:

public int longestCommonSubSequence(String s, String t){int[][] dp = new int[s.length() + 1][t.length() + 1];for(int i = 1; i <= s.length(); i++){for(int j = 1; j <= t.length(); j++){dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);if(s.charAt(i - 1) == t.charAt(j - 1))dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + 1);}}return dp[s.length()][t.length()];}

从这里可以看出串和序列的区别。串要求连续,只要有一处不同就不能被后面的利用。但是序列不同,后面的总可以利用前面的结果。所以可以说串是遍历所有的可能,而序列是遍历所有的范围。取最大时,串必须取所有可能的最大,而序列只需要看最大的范围即可。

0 0