LCS 求最长公共子序列

最长公共子序列不需要字符连续出现和字串不同

//LCS 求最长公共子串模板题

 Common Subsequence

描述

A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a strictly increasing sequence <i1, i2, ..., ik> of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = <a, b, f, c> is a subsequence of X = <a, b, c, f, b, c> with index sequence <1, 2, 4, 6>. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.

输入

The program input is from a text file. Each data set in the file contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct.

输出

For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.

样例输入

abcfbc abfcab
programming contest
abcd mnp

样例输出

4
2
0

 

#include<bits/stdc++.h>
using namespace std;
string a,b;
int dp[1001][1001], len1, len2;
void lcs(int i,int j)
{
    for(i=1; i<=len1; i++)
    {
        for(j=1; j<=len2; j++)
        {
            if(a[i-1] == b[j-1])
                dp[i][j] = dp[i-1][j-1] + 1;
            else
                dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
        }
    }
}
int main()
{
    while(cin>>a)
    {
        cin>>b;
        memset(dp, 0, sizeof(dp));
        len1 = a.length();
        len2 = b.length();
        lcs(len1, len2);
        cout<<dp[len1][len2]<<endl;
    }
}

//有可能遇到爆内存的情况,在只求长度的情况下可以把dp数组改为只有两个状态;

void lcs(int i,int j)
{
    for(i=1; i<=len1; i++)
    {
         e^=1; //切换e为1 和 0;
        for(j=1; j<=len2; j++)
        {
            if(a[i-1] == b[j-1])
                dp[e][j] = dp[e^1][j-1] + val[a[i-1]];
            else
                dp[e][j] = max(dp[e^1][j],dp[e][j-1]);
        }
    }
}

//输出最长公共子串上面的代码不变,根据dp数组状态来决定取哪几个元素

#include<bits/stdc++.h>
using namespace std;
string a,b;
int dp[1001][1001], len1, len2;
void lcs(int i,int j)
{
    for(i=1; i<=len1; i++)
    {
        for(j=1; j<=len2; j++)
        {
            if(a[i-1] == b[j-1])
                dp[i][j] = dp[i-1][j-1] + 1;
            else
                dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
        }
    }
}
void printflcs()
{
    char c[1001];
    memset(c, 0, sizeof(c));
    int i = len1;int j = len2;int d=0;
    while(i!=0 && j!=0)
    {
        if(a[i-1] == b[j-1])
        {
            c[d++] = a[--i];
            j--;
        }
        else if(dp[i-1][j] < dp[i][j-1])
            j--;
        else if(dp[i][j-1] <= dp[i-1][j])
            i--;
    }
    for(i=d-1; i>=0; i--)
        cout<<c[i];
    cout<<endl;

}
int main()
{
    while(cin>>a)
    {
        cin>>b;
        memset(dp, 0, sizeof(dp));
        len1 = a.length();
        len2 = b.length();
        lcs(len1, len2);
        printflcs();
        cout<<dp[len1][len2]<<endl;
    }
}

原文地址:https://www.cnblogs.com/xbqdsjh/p/11503671.html

时间: 2024-10-09 14:30:23

LCS 求最长公共子序列的相关文章

LCS求最长公共子序列(DP)

动态规划并不是一种算法,而是一种解决问题的思路.典型的动态规划问题,如最长公共子序列(LCS),最长单调子序列(LIS)等. 动态规划分为四个步骤: 1.判断问题是否具有最优子结构 这里以LCS为例,X={x1,x2,...,xi}:Y={y1,y2,...,yj}.最长公共子序列Z={z1,z2,...,zk}: ①如果xi=yj,那么zk=xi=yj,且Zk-1是序列Xi-1和Yj-1的LCS: ②如果xi≠yj,那么zk≠xi:且Zk是序列Xi-1和Yj的LCS: ③如果xi≠yj,那么z

(hdu step 3.2.2)Common Subsequence(简单dp:求最长公共子序列的长度)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: Common Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 976 Accepted Submission(s): 538   Probl

[algorithm]求最长公共子序列问题

最直白方法:时间复杂度是O(n3), 空间复杂度是常数 reference:http://blog.csdn.net/monkeyandy/article/details/7957263 /** ** [email protected] ** http://blog.csdn.net/MonkeyAndy **/ 首先介绍动态规划方法的相关知识 动态规划方法的基本思想: 分成若干个子问题,先求解子问题,然后根据子问题的解求得原问题的解.经分解得到的子问题往往不是互相独立的.可重复利用! 其核心思

HDU 1243 反恐训练营 (动态规划求最长公共子序列)

反恐训练营 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3040    Accepted Submission(s): 693 Problem Description 当今国际反恐形势很严峻,特别是美国"9.11事件"以后,国际恐怖势力更是有恃无恐,制造了多起骇人听闻的恐怖事件.基于此,各国都十分担心恐怖势力会对本国社会造

【算法】 求最长公共子序列

最长公共子序列 算法这玩意儿我完全是外行,因为从头开始就不是这个专业的再加上从小就对逻辑性强的东西苦手..所以一直没什么机会也没什么兴趣学.去年刚开始学习了python的那段时间曾经碰到过几个算法比较高级的问题,当时觉得果然这不是我的能力能驾驭的了的..总之是先记录了下来,但是对于算法这块将来的拓展和进一步学习,其实我挺没信心的 = = 问题:最长公共子序列问题(Longest Common Sequence) 子序列是指一个字符串抽掉0到若干个字符后剩下的字符串,抽取的字符不一定相邻也不一定有

九度OJ 1042 Coincidence (动态规划求最长公共子序列)

题目1042:Coincidence 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1689 解决:898 题目描述: Find a longest common subsequence of two strings. 输入: First and second line of each input case contain two strings of lowercase character a-z. There are no spaces before, inside or aft

LCS(最长公共子序列)动规算法正确性证明

今天在看代码源文件求diff的原理的时候看到了LCS算法.这个算法应该不陌生,动规的经典算法.具体算法做啥了我就不说了,不知道的可以直接看<算法导论>动态规划那一章.既然看到了就想回忆下,当想到算法正确性的时候,发现这个算法的正确性证明并不好做.于是想了一段时间,里面有几个细节很trick,容易陷进去.想了几轮,现在把证明贴出来,有异议的可以留言一起交流. 先把一些符号和约定说明下: 假设有两个数组,A和B.A[i]为A的第i个元素,A(i)为有A的第一个元素到第i个元素所组成的前缀.m(i,

求最长公共子序列长度

poj 1458  Common Subsequence http://poj.org/problem?id=1458 问题分析: 这个题是求两个序列的最长公共最序列长度,在这里要弄清楚两个问题 1:本题中所有的子序列并没有要求是连续子序列,所以在求最长子序列的时候不连续是允许的 2:哪部分子序列才是最长的 对于给定的 X = < x1, x2, ..., xm > 和 Z = < z1, z2, ..., zk > ,X序列与Z的每一个子序列都含有公共子序列(最小为0),同理,Z

POJ 1458 Common Subsequence (DP+LCS,最长公共子序列)

题意:给定两个字符串,让你找出它们之间最长公共子序列(LCS)的长度. 析:很明显是个DP,就是LCS,一点都没变.设两个序列分别为,A1,A2,...和B1,B2..,d(i, j)表示两个字符串LCS长度. 当A[i] = B[j] 时,这个最长度就是上一个长度加1,即:d(i, j) = d(i-1, j-1) + 1; 当A[i] != B[j] 时,那就是前面的最长长度(因为即使后面的不成立,也不会影响前面的),即:d(i, j) = max{d(i-1, j), d(i, j-1)}