动态规划_公共最长子序列 java

Posted yfyfyf947

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划_公共最长子序列 java相关的知识,希望对你有一定的参考价值。

给定两个字符串,求其公共最长子序列。子序列与子串不同,子序列只需保证元素之间的相对顺序与原字符串一样就行,不要求这些元素连续。如果这个问题用

暴力法来做,可以试想一下一个长为m与一个长为n的字符串,要比较比较C(n,j)(j=1→n)与C(m,i)(i=1→m)是否有相同的并记录最长的序列,总的比较次数为

C(n,1)*C(m,1)*1+C(n,2)*C(m,2)+...+C(n,j)*C(m,j)*j j=min(m,n)。如果用动态规划来做,时间复杂度仅仅是O(mn)。

 

import java.util.LinkedList;

public class LongestCommonSubsequence {
    public static void main(String[] args)
    {
        String s1="123456789";
        String s2="724765626";
        longestCommonSubsequence(s1,s2);
    }
    //求最长子序列的函数
    public static void longestCommonSubsequence(String s1,String s2)
    {
        char[] arr1=s1.toCharArray();
        char[] arr2=s2.toCharArray();
        int m=arr1.length;
        int n=arr2.length;
        //c[i][j]表示arr1中元素0到i与arr2中元素0到j这两个子串的最长公共子序列长度
        int[][] c=new int[m+1][n+1];
        //b[i][j]表示c[i][j]是怎么来的,三种情况,下面详细讨论
        String[][] b=new String[m+1][n+1];
        //初始化c[][],因为空字符串和任意一个字符串的最长公共子序列长度是0
        for(int i=0;i<m;i++)
            c[m][0]=0;
        for(int i=0;i<n;i++)
            c[0][n]=0;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                //如果两字符串i-1和j-1位置上的元素是相同的,则c[i][j]可以从它最近的左上值加1得到,
                if(arr1[i-1]==arr2[j-1])
                {
                    c[i][j]=c[i-1][j-1]+1;
                    b[i][j]="↖";
                }
                //如果不同,则c[i][j]取和它相邻的上面或左面的最大值
                else
                {
                    if(c[i-1][j]>c[i][j-1])
                    {
                        c[i][j]=c[i-1][j];
                        b[i][j]="↑";
                    }
                    else
                    {
                        c[i][j]=c[i][j-1];
                        b[i][j]="←";
                    }    
                }
            }
        }
        //用堆栈的形式储存数据,方便结果的顺序输出
        LinkedList<Character> l=new LinkedList<>();
        
        while(b[m][n]!=null)
        {
            if(b[m][n].equals("↖"))
            {
                l.add(arr1[m-1]);
                m--;
                n--;
            }    
            else if(b[m][n].equals("←"))
                n--;    
            else if(b[m][n].equals("↑"))
                m--;
        }
        //输出堆栈中的元素
        while(l.size()!=0)
        {
            System.out.print(l.removeLast());
        }
    }
}

打印结果

 

以上是关于动态规划_公共最长子序列 java的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子序列_动态规划

动态规划——最长公共子序列与最长公共子串 (含Python实现代码)

算法导论_动态规划_最长公共子序列

动态规划_线性动态规划,区间动态规划

关于用动态规划法求最大公共子序列的问题

动态规划 最长公共子序列 过程图解