最长公共子序列

Posted narisu

tags:

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

问题描述

一个字符串A的子序列被定义成从A中顺次选出若干个字符构成的序列。如A=“cdaad" ,顺次选1,3,5个字符就构成子序列"cad" ,现给定两个字符串,求它们的最长公共子序列。
两个串的长度均小于2000.

输入格式

第一行两个字符串用空格分开。

输出格式

最长序列的长度。

代码

package javaexam;

import java.util.Scanner;

/**
 * @author houhaibushihai
 * Longest common subsequence
 *
 */
public class LongestCS
{
    public static void main(String[] args)
    {
        Scanner input = new Scanner(System.in);
        String a = input.next();
        String b = input.next();
        
        System.out.println(LCS(a, b));
    }
    
    static int LCS(String a, String b)
    {
        // 判断输入是否有空串
        if(a == null || b == null || a.length() == 0 || b.length() == 0)
            return 0;
        
        int[][] matrix = new int[b.length() + 1][a.length() + 1];
        
        // 初始化
        for(int i = 0; i <= b.length(); ++i)
            matrix[i][0] = 0; // 相当于初始化矩阵第零列
        for(int j = 0; j <= a.length(); ++j)
            matrix[0][j] = 0; // 相当于初始化矩阵第零行
        
        for(int i = 0; i < b.length(); ++i)
        {
            for(int j = 0; j < a.length(); ++j)
            {
                if(b.charAt(i) == a.charAt(j))
                    matrix[i+1][j+1] = matrix[i][j] + 1;
                else
                    matrix[i+1][j+1] = Math.max(matrix[i+1][j], matrix[i][j+1]);
            }
        }
        return matrix[b.length()][a.length()];
    }
}

样例测试

abccd aecd
3

问题分析

矩阵的初始化:
\[ \begin{matrix} & & a & b & c & c & d \ & 0 & 0 & 0 & 0 & 0 & 0 \a & 0 & & & & & \e & 0 & & & & & \c & 0 & & & & & \d & 0 & & & & & \end{matrix} \tag{1} \]

矩阵中遍历过程:不相同填副对角线的最大值;相同填主对角线的值 + 1

  1. b[0] = a = a[0];相同填主对角线的值 + 1
    \[ \begin{matrix} & & a & b & c & c & d \ & 0 & 0 & 0 & 0 & 0 & 0 \a & 0 & 1 & & & & \e & 0 & & & & & \c & 0 & & & & & \d & 0 & & & & & \end{matrix} \tag{2} \]

  2. b[0] = a; a[1] = b; b[0]不等于a[1],不相同填副对角线的最大值
    \[ \begin{matrix} & & a & b & c & c & d \ & 0 & 0 & 0 & 0 & 0 & 0 \a & 0 & 1 & 1 & & & \e & 0 & & & & & \c & 0 & & & & & \d & 0 & & & & & \end{matrix} \tag{3} \]

  3. b[0] = a; a[2] = c; b[0]不等于a[2],不相同填副对角线的最大值
    \[ \begin{matrix} & & a & b & c & c & d \ & 0 & 0 & 0 & 0 & 0 & 0 \a & 0 & 1 & 1 & 1 & & \e & 0 & & & & & \c & 0 & & & & & \d & 0 & & & & & \end{matrix} \tag{4} \]

  4. 依遍历规则,可得矩阵
    \[ \begin{matrix} & & a & b & c & c & d \ & 0 & 0 & 0 & 0 & 0 & 0 \a & 0 & 1 & 1 & 1 & 1 & 1 \e & 0 & 1 & 1 & 1 & 1 & 1 \c & 0 & 1 & 1 & 2 & 2 & 2 \d & 0 & 1 & 1 & 2 & 2 & 3 \end{matrix} \tag{5} \]

即:
\[ \begin{matrix} 0 & 0 & 0 & 0 & 0 & 0 \0 & 1 & 1 & 1 & 1 & 1 \0 & 1 & 1 & 1 & 1 & 1 \0 & 1 & 1 & 2 & 2 & 2 \0 & 1 & 1 & 2 & 2 & 3 \end{matrix} \]

由4可知matrix[4][5] = matrix[b.length()][a.length()] = 3

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

最长公共子序列与最长公共字串

最长公共子序列

最长公共子序列

字符串最长公共子序列问题

最长公共子序列

最长公共子序列