5种关于字符串中“最长”问题的解法

(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/77725795冷血之心的博客)


常见的5种关于字符串中“最长”问题:

  1. 最长公共子序列
  2. 最长公共子串
  3. 最长递增子序列
  4. 最长公共前缀
  5. 最长不含重复元素的子串

最长公共子序列

子序列不需要连续,给定两个不同长度的字符串,如何求出最长公共子序列?
递归解法:
[java]  view plain  copy
  1. /** 
  2.      * 最长公共子序列,返回值为长度 
  3.      * @param x 
  4.      * @param y 
  5.      * @return 
  6.      */  
  7.     int longestPublicSubSequence(String x, String y){  
  8.         if(x.length() == 0 || y.length() == 0){  
  9.             return 0;  
  10.         }  
  11.         if(x.charAt(0) == y.charAt(0)){  
  12.             return 1 + longestPublicSubSequence(x.substring(1), y.substring(1));  
  13.         }else{  
  14.             return Math.max(longestPublicSubSequence(x.substring(1), y.substring(0)),   
  15.                     longestPublicSubSequence(x.substring(0), y.substring(1)));  
  16.         }  
  17.     }  
非递归解法:
[java]  view plain  copy
  1. int getLCS(String str, String str2){  
  2.        
  3.        int n1 = str.length();  
  4.        int n2 = str2.length();  
  5.        int[][] dp = new int[n1+1][n2+1];  
  6.        for(int i=1;i<=n1;i++){  
  7.            for(int j=1;j<=n2;j++){  
  8.                if(str.charAt(i-1)==str2.charAt(j-1)){ //此处应该减1.  
  9.                    dp[i][j]=dp[i-1][j-1]+1;  
  10.                }else{  
  11.                    dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);  
  12.                }  
  13.            }  
  14.        }  
  15.        return dp[n1][n2];  
  16.    }  
画图分析,最长公共子序列:

若对应位置字符相等,则可以这样表示:
反之,若不相等,则表示如下:
递归个非递归的区别是,非递归方法中将结果保存在数组中。

最长公共子串

[java]  view plain  copy
  1. /** 
  2.      * 最长公共子串 
  3.      * @param str1 
  4.      * @param str2 
  5.      * @return 
  6.      */  
  7.     int longestPublicSubstring(String str1, String str2){  
  8.         int l1 = str1.length();  
  9.         int l2 = str2.length();  
  10.         int[][] val = new int[l1][l2];  
  11.         for(int i = 0; i < l1; i++){  
  12.             for(int j = 0; j < l2; j++){  
  13.                 if(str1.charAt(i) == str2.charAt(j)){  
  14.                     if(i >= 1 && j >= 1){  
  15.                         val[i][j] = val[i - 1][j - 1] + 1;  
  16.                     }else{  
  17.                         val[i][j] = 1;  
  18.                     }  
  19.                 }else{  
  20.                     val[i][j] = 0;  
  21.                 }  
  22.             }  
  23.         }  
  24.         // 找到val数组中的最大值  
  25.         int max = 0;  
  26.         for(int i = 0; i < l1; i++){  
  27.             for(int j = 0; j < l2; j++){  
  28.                 max = Math.max(val[i][j], max);               
  29.             }  
  30.         }  
  31.         return max;  
  32.     }  
画图分析:


最长递增子序列

这是一道典型的动态规划试题。使用memo[ ]数组保存中间结果
[java]  view plain  copy
  1. /** 
  2.      * 最长递增子序列 动态规划 
  3.      * @param num 
  4.      * @return 
  5.      */  
  6.     public static int LongestLIS(int[] num){  
  7.         if(num.length<1)  
  8.             return 0;  
  9.         // 定义一个memo数组memo[i]表示以num[i]结尾的序列的长度-1  
  10.         int[] memo = new int[num.length];  
  11.         for(int i = 1;i<num.length;i++){  
  12.             for(int j = 0;j<i;j++){  
  13.                 if(num[i]>num[j]){  
  14.                     memo[i] = Math.max(memo[i], 1+memo[j]);  
  15.                 }  
  16.             }  
  17.         }  
  18.         // 遍历memo数组,找到最大值,并且返回max+1;  
  19.         int max = 0;  
  20.         for (int i = 0; i < memo.length; i++) {  
  21.             max = Math.max(max, memo[i]);  
  22.         }  
  23.         return max+1;  
  24.     }  


最长公共前缀

[java]  view plain  copy
  1. /* 
  2.  * 求一个字符串数组的最长公共前缀 
  3.  * Write a function to find the longest common prefix string amongst an array of strings. 
  4.  */  
  5. public class Main {  
  6.      public static void main(String[] args) {  
  7.           String[] s = {"acvxx","axc","aaa"};  
  8.           System.out.println(longestCommonPrefix(s));  
  9.      }  
  10.      public static String longestCommonPrefix(String[] strs) {  
  11.           if(strs == null || strs.length == 0)     
  12.               return "";  
  13.          String pre = strs[0];  
  14.          int i = 1;  
  15.          while(i < strs.length){  
  16.              while(strs[i].indexOf(pre) != 0)  // 字符串String的indexOf方法使用  
  17.                  pre = pre.substring(0,pre.length()-1);  
  18.              i++;  
  19.          }  
  20.          return pre;  
  21.     }  
  22. }  
该方法巧妙之处就是充分利用了indexOf( )方法,先将数组中的第一个元素作为最长前缀,然后向后遍历数组,判断是否是后边字符串的前缀,若不是,则从后边减小该前缀,直到最后前缀为“”。

最长不含重复元素的子串

本题详见本人博客:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值