【算法学习】最长公共子序列(Java)

一、题目描述

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。
若这两个字符串没有公共子序列,则返回 0。
示例 1:
输入:text1 = “abcde”, text2 = “ace”
输出:3
解释:最长公共子序列是 “ace”,它的长度为 3。
示例 2:
输入:text1 = “abc”, text2 = “abc”
输出:3
解释:最长公共子序列是 “abc”,它的长度为 3。
示例 3:
输入:text1 = “abc”, text2 = “def”
输出:0
解释:两个字符串没有公共子序列,返回 0。

二、思路分析

子序列问题具有两个以下两个性质

  • 最有子结构
  • 重叠子问题

有两个数组 A 和 B
Aa 数组 [A1,A2…Aa-1,Aa]
Bb 数组 [B1,B2…Bb-1,Bb]

设 Aa 和 Bb 的最长公共子序列为 Zz

  1. 如果 Aa = Bb 则 Aa = Bb = Zz , Aa-1 和 Bb-1 的最长公共子序列为 Zz-1
  2. 如果 Aa ≠ Bb 并且 Aa ≠ Zz ,Aa-1 和 Bb 的最长公共子序列为 Zz
  3. 如果 Aa ≠ Bb 并且 Bb ≠ Zz ,Aa 和 Bb-1 的最长公共子序列为 Zz

根据以上三条可以使用动态规划方式解决这个问题,设数组 T[a][b] 用于存储最长公共子序列的情况,
T [ a ] [ b ] = { 0 if  a = 0 , b = 0 T [ a − 1 ] [ b − 1 ] + 1 if  a , b > 0 , A a = B b m a x ( T [ a ] [ b − 1 ] , T [ a − 1 ] [ b ] ) if  a , b > 0 , A a ≠ B b T[a][b] = \begin{cases} 0 &\text{if } a = 0,b = 0 \\ T[a-1][b-1]+1 &\text{if } a,b>0,A_a = B_b\\ max(T[a][b-1],T[a-1][b]) &\text{if } a,b>0,A_a ≠ B_b \end{cases} T[a][b]=0T[a1][b1]+1max(T[a][b1],T[a1][b])if a=0,b=0if a,b>0,Aa=Bbif a,b>0,Aa=Bb

以 A = “abcde”, B = “ace” 为例,其中为方便处理 0行0列默认填充为0

abcde
000000
a011111
c011222
e011223

三、参考代码

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int length1 = text1.length();
        int length2 = text2.length();
        int[][] a = new int[length1 + 1][length2 + 1];//0行0列保留
        for(int i = 1; i <= length1; i++){
            for(int j = 1; j <= length2; j++){
                if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
                    a[i][j] = a[i - 1][j - 1] + 1;
                } else {
                    if (a[i][j - 1] > a[i-1][j]) {
                        a[i][j] = a[i][j - 1];
                    } else {
                        a[i][j] = a[i - 1][j];
                    }
                }
            }
        }
        return a[length1][length2];
    }
}

四、测试连接

力扣

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鼠晓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值