最长公共子序列&最长公共子串

来源:互联网 发布:mysql大数据量查询 编辑:程序博客网 时间:2024/05/22 14:50

最长公共子序列 & 最长公共子串的区别:

找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。而最长公共子序列则并不要求连续。最长公共子序列的问题参考:最长公共子序列。

这两个问题,我都使用动态规划求解。下面说明思路:


1,对于最长公共子串,我设置一个flag[][]数组

对于flag[i][j],表示,
字符串str1中,最后一个字符是str1.charAt(i)的子串,
和str2中,最后一个字符是str2.charAt(j)的子串,
两个子串的最长公共子串长度


也就是说,两个子串,要包括最后一个字符,如果最后一个字符不相等,那么显然,这两个子串不相等,不是公共子串

如果相等,那么flag[i][j]=flag[i-1][j-1]+1

/** * 最长公共子串 * @param str1 * @param str2 */public void lcs(String str1,String str2){/** * 对于flag[i][j],表示, * 字符串str1中,最后一个字符是str1.charAt(i)的子串, * 和str2中,最后一个字符是str2.charAt(j)的子串, * 两个子串的最长公共子串长度 */int flag[][] = new int[str1.length()][str2.length()];int max = 0;int last = 0;//标记公共子串的最后一个节点indexfor(int i=0;i<str1.length();i++){for(int j=0;j<str2.length();j++){if(str1.charAt(i)==str2.charAt(j)){//对于下一个位置的两个字符,必须相同,否则就是0if(i==0||j==0) flag[i][j] = 1;//起始位置是1else flag[i][j] = flag[i-1][j-1]+1;//否则加1if(flag[i][j]>max){//更新最大值max = flag[i][j];last = i;}}}}System.out.println(str1.substring(last-max+1,last+1));}

2,对于最长公共子序列,我设置一个flag[][]数组

对于flag[i][j],表示,
字符串str1,从0-i的子串
和str2中,从0-j的子串
两个子串的最长公共子序列


也就是说,如果最后一个字符相等,那么显然,lag[i][j]=flag[i-1][j-1]+1

如果不相等,我们还要判断,例如

str1最后一个字符,会不会跟str2之前的字符相同

或者str2最后一个字符,会不会跟str1之前的字符相同

两者取较大的

/**     * 最长公共子序列     * @param str1     * @param str2     */    public void lcs2(String str1,String str2){                /**         * 对于flag[i][j],表示,         * 字符串str1,从0-i的子串         * 和str2中,从0-j的子串         * 两个子串的最长公共子序列          */        int flag[][] = new int[str1.length()][str2.length()];        for(int i=0;i<str1.length();i++){            for(int j=0;j<str2.length();j++){                if(i == 0 || j == 0){//起始是0                    flag[i][j] = 0;                }else if(str1.charAt(i)==str2.charAt(j)){//如果某位相同,说明加1                    flag[i][j] = flag[i-1][j-1]+1;                 }else{//如果不同,找出较大的                    flag[i][j] = Math.max(flag[i][j-1],flag[i-1][j]);                }            }        }    }            



0 0
原创粉丝点击