POJ 2250 Compromise (线性dp LCS +递归路径)

Compromise

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 6735   Accepted: 3009   Special Judge

Description

In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfilled, and this is not a trivial task for the countries (maybe except
for Luxembourg). To enforce that Germany will fulfill the criteria, our government has so many wonderful options (raise taxes, sell stocks, revalue the gold reserves,...) that it is really hard to choose what to do.

Therefore the German government requires a program for the following task:

Two politicians each enter their proposal of what to do. The computer then outputs the longest common subsequence of words that occurs in both proposals. As you can see, this is a totally fair compromise (after all, a common sequence of words is something what
both people have in mind).

Your country needs this program, so your job is to write it for us.

Input

The input will contain several test cases.

Each test case consists of two texts. Each text is given as a sequence of lower-case words, separated by whitespace, but with no punctuation. Words will be less than 30 characters long. Both texts will contain less than 100 words and will be terminated by a
line containing a single ‘#‘.

Input is terminated by end of file.

Output

For each test case, print the longest common subsequence of words occuring in the two texts. If there is more than one such sequence, any one is acceptable. Separate the words by one blank. After the
last word, output a newline character.

Sample Input

die einkommen der landwirte
sind fuer die abgeordneten ein buch mit sieben siegeln
um dem abzuhelfen
muessen dringend alle subventionsgesetze verbessert werden
#
die steuern auf vermoegen und einkommen
sollten nach meinung der abgeordneten
nachdruecklich erhoben werden
dazu muessen die kontrollbefugnisse der finanzbehoerden
dringend verbessert werden
#

Sample Output

die einkommen der abgeordneten muessen dringend verbessert werden

Source

Ulm Local 1997

题目链接:http://poj.org/problem?id=2250

题目大意:求两个段落中单词的最大公共子序列并输出它们

题目分析:裸的LCS题,因为是单词,用string就行了,二维字符数组也可以,然后用一个数组记录一下路径

关于LCS即最长公共子序列的状态状态转移方程解释一下:

dp[i][j]表示第一个表示A的前i位和B的前j位的最长公共子序列的长度,那么有三种情况

1.若A[i - 1] == B[j - 1],dp[i][j] = dp[i - 1][j - 1] + 1 即如果A[i - 1] == B[j - 1],则这一组相同的情况记录下即+1,接着我们只要继续比较A的前i-1和B的前j-1部分

2.若dp[i - 1][j] > dp[i][j - 1],dp[i][j] = dp[i - 1][j]即A的前i-1位和B的前j位的LCS大于A的前i位和B的前j-1位,则我们取大的

3.若dp[i - 1][j] < dp[i][j - 1],dp[i][j] = dp[i][j - 1]

本题需要记录路径,我们用path数组,若为情况1则path[i][j] = 0, 若为情况2则path[i][j] = 1, 否则path[i][j] = -1,然后递归记录答案

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
int dp[105][105];
int path[105][105];
string ans[105];
string a[105], b[105];
int cnta, cntb, cnt, num;

void init()
{
    cnt = cnta = cntb = num = 0;
    memset(dp, 0, sizeof(dp));
    memset(path, 0, sizeof(path));
}

void Get(int i, int j)
{
    if(!i || !j)
        return;
    if(path[i][j] == 0)
    {
        Get(i - 1, j - 1);
        ans[num ++] = a[i - 1];
    }
    else if(path[i][j] == 1)
        Get(i - 1, j);
    else
        Get(i, j - 1);
}

int main()
{
    string s;
    init();
    while(cin >> s)
    {
        if(s[0] == '#')
            cnt ++;
        if(cnt == 0 && s[0] != '#')
            a[cnta ++] = s;
        if(cnt == 1 && s[0] != '#')
            b[cntb ++] = s;
        if(cnt == 2)
        {
            for(int i = 1; i <= cnta; i++)
            {
                for(int j = 1; j <= cntb; j++)
                {
                    if(a[i - 1] == b[j - 1])
                    {
                        dp[i][j] = dp[i - 1][j - 1] + 1;
                        path[i][j] = 0;
                    }
                    else if(dp[i - 1][j] > dp[i][j - 1])
                    {
                        dp[i][j] = dp[i - 1][j];
                        path[i][j] = 1;
                    }
                    else
                    {
                        dp[i][j] = dp[i][j - 1];
                        path[i][j] = -1;
                    }
                }
            }
            Get(cnta, cntb);
            for(int i = 0; i < num - 1; i++)
                cout << ans[i] << " ";
            cout << ans[num - 1] << endl;
            init();
        }
    }
}
时间: 2024-10-15 07:45:13

POJ 2250 Compromise (线性dp LCS +递归路径)的相关文章

poj 2250 Compromise dp lcs 路径输出

点击打开链接题目链接 Compromise Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6520   Accepted: 2922   Special Judge Description In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria

POJ 2250 Compromise (DP,最长公共子序列)

Compromise Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6440 Accepted: 2882 Special Judge Description In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfille

周赛 POJ 2250 Compromise

Description In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfilled, and this is not a trivial task for the countries (maybe except for Luxembourg). To enforce that Germa

LIS POJ 2250 Compromise

题目传送门 1 /* 2 LIS模板题:题目看错了,是求单词的最长上升子序列! 3 编程好累:) 4 */ 5 #include <cstdio> 6 #include <iostream> 7 #include <cstring> 8 #include <algorithm> 9 #include <string> 10 using namespace std; 11 12 const int MAXN = 1e2 + 10; 13 const

POJ 2479-Maximum sum(线性dp)

Maximum sum Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33918   Accepted: 10504 Description Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below: Your task is to calculate d(A). Input The input consists o

POJ 2250 Compromise(最长公共子序列LCS)

http://poj.org/problem?id=2250 题意: 给你两段由空格分隔的语句, 要你求该两段语句的最长公共子序列. 且随便输出一个解即可. 注意每个单词需要看成我们一般处理字符串子序列的一个单独字符. 即每个单词是一个整体. 分析: 与往常计算最长公共子序列一样的方式即可. 然后用DFS输出序列即可.本题与POJ1458提供的解法本质一样. http://blog.csdn.net/u013480600/article/details/40741333 AC代码: #inclu

poj 2250 Compromise (LCS)

题目大意:给出两段文字,求出最长的公共单词串. 直接是以前的代码改一点就A了. #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; char s1[35][100],s2[35][100],s[35][100]; int len1,len2,dp[105][105],mark[105][105],l; void LCS() { int i,j; memset(d

POJ 1458-Common Subsequence(线性dp/LCS)

Common Subsequence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39009   Accepted: 15713 Description A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, ..

POJ 2250 Compromise (UVA 531)

LCS问题,基础DP. 让我很忧伤的WA了很多次.只是一个LCS问题,需要记录一下路径. 自己的想办法记录path出错,最后只好用标记. 没有什么优化,二维数组,递归打印,cin.eof() 来识别 end of file 标识. 至于单词用map 映射的.其实也用不着,直接二维string或者 二维char 然后strcmp 也行. Special Judge 交 UVA 531 奇怪的PE了... 然后改成 flag 标记 输出 空格.终于都AC了. #include<cstdio> #i