(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/77725795冷血之心的博客)
常见的5种关于字符串中“最长”问题:
- 最长公共子序列
- 最长公共子串
- 最长递增子序列
- 最长公共前缀
- 最长不含重复元素的子串
最长公共子序列
子序列不需要连续,给定两个不同长度的字符串,如何求出最长公共子序列?
递归解法:
-
-
-
-
-
-
- int longestPublicSubSequence(String x, String y){
- if(x.length() == 0 || y.length() == 0){
- return 0;
- }
- if(x.charAt(0) == y.charAt(0)){
- return 1 + longestPublicSubSequence(x.substring(1), y.substring(1));
- }else{
- return Math.max(longestPublicSubSequence(x.substring(1), y.substring(0)),
- longestPublicSubSequence(x.substring(0), y.substring(1)));
- }
- }
非递归解法:
- int getLCS(String str, String str2){
-
- int n1 = str.length();
- int n2 = str2.length();
- int[][] dp = new int[n1+1][n2+1];
- for(int i=1;i<=n1;i++){
- for(int j=1;j<=n2;j++){
- if(str.charAt(i-1)==str2.charAt(j-1)){
- dp[i][j]=dp[i-1][j-1]+1;
- }else{
- dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
- }
- }
- }
- return dp[n1][n2];
- }
画图分析,最长公共子序列:
若对应位置字符相等,则可以这样表示:
反之,若不相等,则表示如下:
递归个非递归的区别是,非递归方法中将结果保存在数组中。
最长公共子串
-
-
-
-
-
-
- int longestPublicSubstring(String str1, String str2){
- int l1 = str1.length();
- int l2 = str2.length();
- int[][] val = new int[l1][l2];
- for(int i = 0; i < l1; i++){
- for(int j = 0; j < l2; j++){
- if(str1.charAt(i) == str2.charAt(j)){
- if(i >= 1 && j >= 1){
- val[i][j] = val[i - 1][j - 1] + 1;
- }else{
- val[i][j] = 1;
- }
- }else{
- val[i][j] = 0;
- }
- }
- }
-
- int max = 0;
- for(int i = 0; i < l1; i++){
- for(int j = 0; j < l2; j++){
- max = Math.max(val[i][j], max);
- }
- }
- return max;
- }
画图分析:
最长递增子序列
这是一道典型的动态规划试题。使用memo[ ]数组保存中间结果
-
-
-
-
-
- public static int LongestLIS(int[] num){
- if(num.length<1)
- return 0;
-
- int[] memo = new int[num.length];
- for(int i = 1;i<num.length;i++){
- for(int j = 0;j<i;j++){
- if(num[i]>num[j]){
- memo[i] = Math.max(memo[i], 1+memo[j]);
- }
- }
- }
-
- int max = 0;
- for (int i = 0; i < memo.length; i++) {
- max = Math.max(max, memo[i]);
- }
- return max+1;
- }
最长公共前缀
-
-
-
-
- public class Main {
- public static void main(String[] args) {
- String[] s = {"acvxx","axc","aaa"};
- System.out.println(longestCommonPrefix(s));
- }
- public static String longestCommonPrefix(String[] strs) {
- if(strs == null || strs.length == 0)
- return "";
- String pre = strs[0];
- int i = 1;
- while(i < strs.length){
- while(strs[i].indexOf(pre) != 0)
- pre = pre.substring(0,pre.length()-1);
- i++;
- }
- return pre;
- }
- }
该方法巧妙之处就是充分利用了indexOf( )方法,先将数组中的第一个元素作为最长前缀,然后向后遍历数组,判断是否是后边字符串的前缀,若不是,则从后边减小该前缀,直到最后前缀为“”。
最长不含重复元素的子串
本题详见本人博客: