Java最长公共子序列

问题描述:
最长公共子序列定义:两个或多个已知数列的子序列集合中最长的就是最长公共子序列。
比如数列A = “abcdef”和B = “adefcb”,那么两个数列的公共子序列集合有{”a","ab","abc","adef",等等},其中最长
的就是adef,这就是最长公共子序列。
注意:最长公共子序列的公共子序列里的元素可以不相邻,但是公共子字符串必须是连接在一起的,比如A和B
的公共子字符串是“def”。
用动态规划法来求解最长公共子序列,因为最长公共子序列具有最有子结构性质,可以分成子问题来递归求最优
解,最后组合子问题求解出问题。用c[i][j]记录X[i]与Y[j] 的LCS 的长度,求解问题c[i,j],可以分成c[i­1][j­1]、c[i­
1][j]、c[i][j­1]子问题来求解,依次递堆到最小子问题,动态规划的递归式描述为Java最长公共子序列_第1张图片

时间复杂度分析:

 LongestCommonSubsequence(String str1, String str2)`方法:计算表中每个
元素需要`O(1)`时间,所以此方法的时间复杂度为`O(MN)`。

print(int[][] opt, String X, String Y, int i, int j)`方法:每次递归
中变量i和j中至少增加1.所以该算法时间复杂度为O(M+N)。

public class Main
{
    public static void main(String args[])
    {
        String str1 = "fjssharpword";
        String str2 = "helloworld";
        //计算最长公共子序列矩阵
        int re[][] = LongestCommonSubsequence(str1,str2);
        //打印矩阵
        for(int i = 0;i <= str1.length();i++)
        {
            for(int j = 0;j <= str2.length();j++)
            {
                System.out.print(re[i][j]+" ");
            }
            System.out.println();
        }
        System.out.println();
        System.out.println();
        //输出LCS
        print(re,str1,str2,str1.length(),str2.length());
    }
    //假如返回两个字符串的最长公共子序列的长度
    public static int[][]LongestCommonSubsequence(String str1,String str2)
    {
        //建立二位矩阵
      int matrix[][]= new int[str1.length() + 1][str2.length() + 1];
      //初始化边界条件
        for(int i = 0;i <= str1.length();i++)
        {
            matrix[i][0] = 0;//每行第一列置零
        }
        for(int j = 0;j <= str2.length();j++)
        {
            matrix[0][j] = 0;//每列第一行置零
        }
        //填充矩阵
        for(int i = 1;i <= str1.length();i++)
        {
            for(int j = 1;j <= str2.length();j++)
            {
                if(str1.charAt(i - 1) == str2.charAt(j - 1))
                {
                    matrix[i][j] = matrix[i - 1][j - 1] + 1;
                }
                else
                {
                    matrix[i][j] = (matrix[i - 1][j] >= matrix[i][j - 1]?matrix[i - 1][j]:matrix[i][j - 1]);
                }
            }
        }
        return matrix;
    }
    //根据矩阵输出LCS
    public static void print(int[][] opt,String X,String Y,int i,int j)
    {
        //递归结束条件(任何一个字符串长度为0)
        if(i == 0 || j == 0)
        {
            return;
        }
        //如果x中第i个字符和y中第j个字符相等就递归i - 1,j - 1
        if(X.charAt(i - 1) == Y.charAt(j - 1))
        {
            print(opt,X,Y,i - 1,j - 1);
            System.out.print(X.charAt(i - 1));
        }
        //如果不相等,判断i - 1和j的公共子串的长度与i和j - 1的公共子串的长度
        else if(opt[i - 1][j] >= opt[i][j])
        {
            print(opt,X,Y,i - 1,j);
        }
        else
        {
            print(opt,X,Y,i,j - 1);
        }
    }
}

 

你可能感兴趣的:(Java,我的编程笔记)