牛客NC92 最长公共子序列(二)【中等 动态规划 Java,Go,PHP】

题目

题目链接:

https://www.nowcoder.com/practice/6d29638c85bb4ffd80c020fe244baf11

思路

复制代码
https://blog.csdn.net/qq_36544411/article/details/120021203
思路
动态规划法,
我们以dp[i][j]表示在s1中以第i个元素结尾,s2中以第j个元素结尾的字符串的最长公共子序列长度,
若是i与j相等,则该问题可以变成1+dp[i−1][j−1],即最长公共子序列长度加1,若是不相等,
则换成两个子问题:dp[i][j−1]或者dp[i−1][j],由此用递归或者动态规划即可以解决。

求出递归公式,为
 if s1.charAt(i-1) == s2.charAt(j-1)  dp[i][j]=dp[i-1][j-1]+1
 else  dp[i][j]= Math.max(dp[i-1][j],dp[i][j-1])

反推求出子序列。只需要求其中一个。

参考答案Java

java 复制代码
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * longest common subsequence
     * @param s1 string字符串 the string
     * @param s2 string字符串 the string
     * @return string字符串
     */
    public String LCS (String s1, String s2) {
        /*
           https://blog.csdn.net/qq_36544411/article/details/120021203
           思路
           动态规划法,
           我们以dp[i][j]表示在s1中以第i个元素结尾,s2中以第j个元素结尾的字符串的最长公共子序列长度,
           若是i与j相等,则该问题可以变成1+dp[i−1][j−1],即最长公共子序列长度加1,若是不相等,
           则换成两个子问题:dp[i][j−1]或者dp[i−1][j],由此用递归或者动态规划即可以解决。

           求出递归公式,为
           if s1.charAt(i-1) == s2.charAt(j-1)  dp[i][j]=dp[i-1][j-1]+1
           else  dp[i][j]= Math.max(dp[i-1][j],dp[i][j-1])

           反推求出子序列。只需要求其中一个。

            */
        int n = s1.length();
        int m = s2.length();
        int[][] dp = new int[n + 1][m + 1];
        for (int i = 0; i <= n ; i++) {
            for (int j = 0; j <= m ; j++) {
                if (i == 0 || j == 0) {
                    dp[i][j] = 0;
                } else {

                    if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                        dp[i][j] = dp[i - 1][j - 1] + 1;
                    } else {
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                    }
                }
            }
        }

        Stack<Character> stack = new Stack<>();
        while (n > 0 && m > 0) {
            if (s1.charAt(n - 1) == s2.charAt(m - 1)) {
                stack.add(s1.charAt(n - 1));
                n--;
                m--;
            } else if (dp[n - 1][m] >= dp[n][m - 1]) {
                n--;
            } else {
                m--;
            }
        }

        StringBuilder sb = new StringBuilder();
        while (!stack.isEmpty()) {
            sb.append(stack.pop());
        }

        return sb.length() == 0 ? "-1" : sb.toString();
    }
}

参考答案Go

go 复制代码
package main

import "fmt"

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * longest common subsequence
 * @param s1 string字符串 the string
 * @param s2 string字符串 the string
 * @return string字符串
 */
func LCS(s1 string, s2 string) string {
	/*
	   https://blog.csdn.net/qq_36544411/article/details/120021203
	   思路
	   动态规划法,
	   我们以dp[i][j]表示在s1中以第i个元素结尾,s2中以第j个元素结尾的字符串的最长公共子序列长度,
	   若是i与j相等,则该问题可以变成1+dp[i−1][j−1],即最长公共子序列长度加1,若是不相等,
	   则换成两个子问题:dp[i][j−1]或者dp[i−1][j],由此用递归或者动态规划即可以解决。

	   求出递归公式,为
	   if s1.charAt(i-1) == s2.charAt(j-1)  dp[i][j]=dp[i-1][j-1]+1
	   else  dp[i][j]= Math.max(dp[i-1][j],dp[i][j-1])

	   反推求出子序列。只需要求其中一个。
	*/

	n := len(s1)
	m := len(s2)
	dp := make([][]int, n+1)
	for i := 0; i <= n; i++ {
		dp[i] = make([]int, m+1)
	}

	for i := 0; i <= n; i++ {
		for j := 0; j <= m; j++ {
			if i == 0 || j == 0 {
				dp[i][j] = 0
			} else {
				if s1[i-1] == s2[j-1] {
					dp[i][j] = dp[i-1][j-1] + 1
				} else {
					cur1 := dp[i-1][j]
					cur2 := dp[i][j-1]
					if cur1 > cur2 {
						dp[i][j] = cur1
					} else {
						dp[i][j] = cur2
					}
				}
			}
		}
	}

	stack := []byte{}
	for n > 0 && m > 0 {
		if s1[n-1] == s2[m-1] {
			stack = append(stack, s1[n-1])
			n--
			m--
		} else if dp[n-1][m] >= dp[n][m-1] {
			n--
		} else {
			m--
		}
	}

	s3 := ""
	for k := len(stack) - 1; k >= 0; k-- {
		s3 = fmt.Sprintf("%s%s", s3, string(stack[k]))
	}

	if len(s3) == 0 {
		return "-1"
	} else {
		return s3
	}
}

参考答案PHP

java 复制代码
<?php


/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * longest common subsequence
 * @param s1 string字符串 the string
 * @param s2 string字符串 the string
 * @return string字符串
 */
function LCS( $s1 ,  $s2 )
{
     /*
	   https://blog.csdn.net/qq_36544411/article/details/120021203
	   思路
	   动态规划法,
	   我们以dp[i][j]表示在s1中以第i个元素结尾,s2中以第j个元素结尾的字符串的最长公共子序列长度,
	   若是i与j相等,则该问题可以变成1+dp[i−1][j−1],即最长公共子序列长度加1,若是不相等,
	   则换成两个子问题:dp[i][j−1]或者dp[i−1][j],由此用递归或者动态规划即可以解决。

	   求出递归公式,为
	   if s1.charAt(i-1) == s2.charAt(j-1)  dp[i][j]=dp[i-1][j-1]+1
	   else  dp[i][j]= Math.max(dp[i-1][j],dp[i][j-1])

	   反推求出子序列。只需要求其中一个。
	*/

    $n=strlen($s1);
    $m= strlen($s2);
    $dp=array();
    for($i=0;$i<=$n;$i++){
        for($j=0;$j<=$m;$j++){
            if($i==0 || $j==0){
                $dp[$i][$j]=0;
            }else{
                if($s1[$i-1] == $s2[$j-1]){
                    $dp[$i][$j]=$dp[$i-1][$j-1]+1;
                }else{
                    $cur1= $dp[$i-1][$j];
                    $cur2 = $dp[$i][$j-1];

                    if($cur1>$cur2){
                        $dp[$i][$j] = $cur1;
                    }else{
                        $dp[$i][$j] = $cur2;
                    }
                }
            }
        }
    }

    $stack = array();
    $idx=0;
    while ($n>0 && $m>0){
        if($s1[$n-1] == $s2[$m-1]){
            $stack[$idx++] = $s1[$n-1];
            $n--;
            $m--;
        }else if($dp[$n-1][$m]>= $dp[$n][$m-1]){
            $n--;
        }else{
            $m--;
        }
    }

    if($idx==0) return "-1";
    $s3="";
    for(--$idx;$idx>=0;$idx--){
        $s3.=$stack[$idx];
    }

    return $s3;
}
相关推荐
SweetCode8 分钟前
裴蜀定理:整数解的奥秘
数据结构·python·线性代数·算法·机器学习
ゞ 正在缓冲99%…21 分钟前
leetcode76.最小覆盖子串
java·算法·leetcode·字符串·双指针·滑动窗口
xuanjiong22 分钟前
纯个人整理,蓝桥杯使用的算法模板day2(0-1背包问题),手打个人理解注释,超全面,且均已验证成功(附带详细手写“模拟流程图”,全网首个
算法·蓝桥杯·动态规划
惊鸿.Jh41 分钟前
【滑动窗口】3254. 长度为 K 的子数组的能量值 I
数据结构·算法·leetcode
明灯L42 分钟前
《函数基础与内存机制深度剖析:从 return 语句到各类经典编程题详解》
经验分享·python·算法·链表·经典例题
碳基学AI1 小时前
哈尔滨工业大学DeepSeek公开课:探索大模型原理、技术与应用从GPT到DeepSeek|附视频与讲义免费下载方法
大数据·人工智能·python·gpt·算法·语言模型·集成学习
补三补四1 小时前
机器学习-聚类分析算法
人工智能·深度学习·算法·机器学习
独好紫罗兰1 小时前
洛谷题单3-P5718 【深基4.例2】找最小值-python-流程图重构
开发语言·python·算法
好好学习^按时吃饭1 小时前
[NOIP 1999 提高组] 导弹拦截
动态规划
正脉科工 CAE仿真1 小时前
基于ANSYS 概率设计和APDL编程的结构可靠性设计分析
人工智能·python·算法