HDU 1503 Advanced Fruits 最长公共子序列(LCS)

题目https://cn.vjudge.net/problem/HDU-1503

题意:输入两个长度不超过一百的非空字符串,求一个字符串,使该字符串存在子序列分别是输入的两字符串,要求所求字符串最短。有多个答案时,输出任意一个。

思路:要找最短的包含两字符串的字符串,把输入的两字符串,公共部分输出一次,其他部分按照一定顺序各自输出。具体做法:找出最长公共子序列,标记好LCS的每个字符在原字符串中对应的下标,然后以这些匹配的位置将字符串分段输出即可。
例如:
例图
上图S1, S2两字符串,a b两字符分别对应匹配
那么答案即是
S1part1 + S2part1 + a + S1part2 + S2part2 + b + S1part3 + S2part3
或者
S2part1 + S1part1 + a + S2part2 + S1part2 + b + S2part3 + S1part3

代码:C++

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 100 + 10;

string s1, s2;
int n1, n2;

int d[maxn][maxn];
int p[maxn][maxn]; // -1, 0, 1, 2

void LCS()
{
    memset(d, 0, sizeof(d));
    memset(p, -1, sizeof(p));
    for (int i = 0; i < n1; i++)
    {
        for (int j = 0; j < n2; j++)
        {
            if (s1[i] == s2[j])
            {
                if (i == 0 || j == 0)
                {
                    d[i][j] = 1;
                }
                else
                {
                    d[i][j] = d[i - 1][j - 1] + 1;
                }
                p[i][j] = 0;
            }
            if (i != 0 && d[i - 1][j] > d[i][j])
            {
                d[i][j] = d[i - 1][j];
                p[i][j] = 1;
            }
            if (j != 0 && d[i][j - 1] > d[i][j])
            {
                d[i][j] = d[i][j - 1];
                p[i][j] = 2;
            }
        }
    }
}

void print()
{
    string ans = "";
    int i = n1 - 1, j = n2 - 1;
    int prei = i, prej = j;
    while (i >= 0 && j >= 0)
    {
        if (p[i][j] == 0)
        {
            for (int k = prej; k > j; k--)
            {
                ans.push_back(s2[k]);
            }
            for (int k = prei; k > i; k--)
            {
                ans.push_back(s1[k]);
            }
            ans.push_back(s1[i]);
            i--;
            j--;
            prei = i;
            prej = j;
        }
        else if (p[i][j] == 1)
        {
            i--;
        }
        else if(p[i][j] == 2)
        {
            j--;
        }
        else //if(p[i][j] == -1)
        {
            break;
        }
    }
    for (int k = prej; k >= 0; k--)
    {
        ans.push_back(s2[k]);
    }
    for (int k = prei; k >= 0; k--)
    {
        ans.push_back(s1[k]);
    }
    reverse(ans.begin(), ans.end());
    cout << ans << endl;
}

int main()
{
    while (cin >> s1 >> s2)
    {
        n1 = s1.size();
        n2 = s2.size();
        LCS();
        print();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Rewriter_huanying/article/details/88398258