HDOJ 1159-Common Subsequence

HDOJ 1159-Common Subsequence

Common Subsequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 59402    Accepted Submission(s): 27503

Problem DescriptionA 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.

Sample Input

abcfbc abfcab
programming contest 
abcd mnp

Sample Output

4
2
0

SourceSoutheastern Europe 2003
RecommendIgnatius   |   We have carefully selected several similar problems for you:  10871176100310581069


求最长公共子序列。DP模板题,使用一个dp数组即可,用pre记录原来左上角的值。 代码如下,如果要求出一个lcs,参考《算法导论》P225,使用一个二维数组direction记录每个格子最大值来自哪个方向,重构lcs时从右下角不停的往前找。

#include <string>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int lcs(const string& a, const string& b)
{
    int n = a.size(), m = b.size();
    if (n == 0 || m == 0)
        return 0;
    vector<int> dp(m + 1, 0);
    for (int i = 1; i <= n; ++i) {
        int pre = 0;
        for (int j = 1; j <= m; ++j) {
            int cur = 0;
            if (a[i – 1] == b[j – 1])
                cur = pre + 1;
            else
                cur = max(dp[j – 1], dp[j]);
            pre = dp[j];
            dp[j] = cur;
        }
    }
    return dp[m]; // 最大值就是右下角的值
}
void construct_lcs(vector<vector<int> >& direction, const string& a, int i, int j, string& lcs)
{
    if (i == 0 || j == 0)
        return;
    if (direction[i][j] == 3) {
        construct_lcs(direction, a, i – 1, j – 1, lcs);
        lcs += string(1, a[i – 1]); // direction下标1对应a下标0,所以i-1
    }
    else if (direction[i][j] == 2) {
        construct_lcs(direction, a, i – 1, j, lcs);
    }
    else {
        construct_lcs(direction, a, i, j – 1, lcs);
    }
}
string lcs_string(const string& a, const string& b)
{
    int n = a.size(), m = b.size();
    if (n == 0 || m == 0)
        return 0;
    vector<int> dp(m + 1, 0);
    vector<vector<int> > direction(n + 1, vector<int>(m + 1, 0)); // 1:left,2:up,3:diagonal
    for (int i = 1; i <= n; ++i) {
        int pre = 0;
        for (int j = 1; j <= m; ++j) {
            int cur = 0;
            if (a[i – 1] == b[j – 1]) {
                cur = pre + 1;
                direction[i][j] = 3;
            }
            else {
                if (dp[j – 1] > dp[j]) {
                    cur = dp[j – 1];
                    direction[i][j] = 1;
                }
                else {
                    cur = dp[j];
                    direction[i][j] = 2;
                }
            }
            pre = dp[j];
            dp[j] = cur;
        }
    }
    string ans;
    construct_lcs(direction, a, n, m, ans); // 从右下角递归往前找,LCRS P225
    return ans;
}
int main()
{
    //freopen("input.txt", "r", stdin);
    string a, b;
    while (cin >> a >> b) {
        cout << lcs(a, b) << endl;
        //cout << lcs(a, b) << "\t" << lcs_string(a, b) << endl;;
    }
    return 0;
}

本代码提交AC,用时46MS。

Leave a Reply

Your email address will not be published. Required fields are marked *