b_nk_最长公共子序列 & 最长公共子串(dp+双指针 | 记录最长lms的长度,以及结尾位置)

最长公共子序列

给出两个字符串A B,求A与B的最长公共子序列字符串

思路:一开始直接字符串拼接做的,t了

String f[][];
String my_max(String a, String b) {
    return (a.length()<b.length() ? b : a);
}
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++) {
    if (s[i]==t[j]) f[i][j]=f[i-1][j-1]+s[i];
    else f[i][j]=my_max(f[i-1][j], f[i][j-1]);
}

优化:我没有用好f[i][j]的意义,我只需要求出f[i][j]的最长长度,然后双指针判断就行了,逻辑见注释

import java.util.*;
import java.math.*;
import java.io.*;
class Solution {
    int N=1005, n,m,f[][];
    String get_lms(char[] s, char[] t) {
        int i=n, j=m;
        StringBuilder ans=new StringBuilder();
        while (i>0 && j>0) {
            if (s[i]==t[j]) {
                ans.append(s[i]);
                i--; j--;
            } else { //(s的前i-1个字符和t的前j个的lms」比「s的前i个和t的前j-1个的lms)短,则证明我保留s的第i个字符更优
                if (f[i-1][j]<f[i][j-1]) j--;
                else i--;
            }
        }
        return ans.reverse().toString();
    }
    void init() {
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        String a=sc.next(), b=sc.next();
        f=new int[N][N]; n=a.length(); m=b.length();
        a=' '+a; b=' '+b;
        char s[]=a.toCharArray(), t[]=b.toCharArray();

        for (int i=1; i<=n; i++)
        for (int j=1; j<=m; j++) {
            if (s[i]==t[j]) f[i][j]=f[i-1][j-1]+s[i];
            else f[i][j]=Math.max(f[i-1][j], f[i][j-1]);
        }
        System.out.println(get_lms(s,t));
    }
}
public class Main{
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
        s.init();
    }
}

最长公共子串

给定两个字符串str1和str2,输出两个字符串的最长公共子串,如果最长公共子串为空,输出-1。

思路:记录最长长度与达到最长长度时的子串的结尾位置

const int N=5005;
class Solution {
public:
    int f[N][N]; 
    string LCS(string s, string t) {
        int n=s.size(), m=t.size(), maxL=0, e=-1;
        for (int i=1; i<=n; i++)
        for (int j=1; j<=m; j++) {
            if (s[i-1]==t[j-1]) {
                f[i][j]=f[i-1][j-1]+1;
            } else {
                f[i][j]=0;
            }
            if (f[i][j]>maxL)
                maxL=f[i][j], e=i-1;
        }
        if (e==-1) return "-1";
        return s.substr(e-maxL+1, maxL);
    }
};
posted @ 2020-10-27 11:18  童年の波鞋  阅读(259)  评论(0编辑  收藏  举报