• 51nod【1006 最长公共子序列Lcs 】


    给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。
    比如两个串为:
    abcicba
    abdkscab
    ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。
    Input
    第1行:字符串A
    第2行:字符串B
    (A,B的长度 <= 1000)
    Output
    输出最长的子序列,如果有多个,随意输出1个。
    Input示例
    abcicba
    abdkscab
    Output示例
    abca

    • 题解:
      • dp[i][j] 表示字符串A以第i个位置 ,字符串B以第j个位置的最长公共子序列的长度
      • dp[i][j] = dp[i - 1][j - 1] + 1 if a[i] == a[j]
      • else dp[i][j] == max(dp[i - 1][j] , dp[i][j - 1]);
      • 最大长度就是 dp[n][m] ,n 为A的长度 ,m为B的长度
      • 还原字符串 ,只需要回到 dp[i][j] 刚开始发生改变的地方即可
    • 代码:
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <set>
    #include <map>
    using namespace std;
    const int maxn=1005;
    int dp[maxn][maxn];
    char path[maxn];
    char a[maxn],b[maxn];
    void lcs(int n,int m){
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(a[i]==b[j]){
                    dp[i+1][j+1]=dp[i][j]+1;
                }else {
                    dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);
                }
            }
        }
    
    }
    int main()
    {
        scanf("%s",a);
        scanf("%s",b);
        int lena=strlen(a);
        int lenb=strlen(b);
        int plen=0;
        lcs(lena,lenb);
        int i=lena-1;
        int j=lenb-1;
        while(i>=0&&j>=0){
            if(a[i]==b[j]){
                path[plen++]=a[i];
                i--;
                j--;
            }else if(dp[i+1][j]>=dp[i][j+1]){
                j--;
            }else {
                i--;
            }
        }
        reverse(path,path+plen);
        puts(path);
        return 0;
    }
    

  • 相关阅读:
    poj2823单调队列认知
    有关二叉树的三序遍历的题目
    hdu4757 可持续字典树
    ZOJ2532判断边是否是割集中的边
    poj2455 k条路最小化最长边
    乘法逆元模板
    poj1699 KMP+壮压DP
    Innodb存储引擎——非聚集索引
    java集合框架笔记
    jvm垃圾回收
  • 原文地址:https://www.cnblogs.com/kzbin/p/9205204.html
Copyright © 2020-2023  润新知